diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..bf217e22
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,17 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
+
+[*.{ts,js,json}]
+quote_type = double
+indent_style = space
+indent_size = 4
diff --git a/.eslintrc.json b/.eslintrc.json
index b2c96ed0..68da0e51 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -8,7 +8,6 @@
"GLOBALS": true,
"VIEW_DATA": true
},
- "ecmaFeatures": {},
"rules": {
"no-alert": "off",
"no-array-constructor": "error",
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 00000000..c6fa4427
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,37 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ node-version: [16.x, 18.x, 20.x]
+ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ - run: npm ci
+ - run: npm run ci
+
+ - name: Publish Unit Test Results
+ uses: EnricoMi/publish-unit-test-result-action@v2
+ if: always()
+ with:
+ files: junit.xml
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index d4858477..a794b5d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
.DS_Store
+.idea
node_modules
**/*~
**/.#*
+coverage
+junit.xml
diff --git a/.travis.yml b/.travis.yml
index 6ecc2b7e..899a1c97 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
language: node_js
node_js:
- - "6"
+ - "10"
before_script:
- npm install
diff --git a/CHANGELOG.md b/CHANGELOG.md
old mode 100644
new mode 100755
index e54f8d97..23148359
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,256 @@
# Changelog
+## Version 1.1.16
+
+- Fix errors in `view_thread` event handler. Thanks @ek23 !
+
+## Version 1.1.15
+
+- Fix errors in typescript type-definitions. Thanks @BasSchoutenTribe !
+ (No changes in runtime code)
+
+## Version 1.1.14
+
+- Fix regression in DOM observers, introduced in 1.1.13. Thanks @kinkoazc!
+
+## Version 1.1.13
+
+- Drop bundled jQuery, support jQuery 4, support explicit no-jQuery mode
+- Fix reply button selector to support Gmail in text labels mode
+- Fix `api.get.user_email()`.
+
+## Version 1.1.12
+
+- Use MutationObserver for DOM Node changes. Thanks @cancan101!
+- Fix issue in `api.dom.compose.is_inline()`. Thanks @MadcowD!
+
+## Version 1.1.11
+
+- Fix `api.observe.on("view_email", ...)` not working.
+
+## Version 1.1.10
+
+- Fix `api.dom.right_toolbar()`, by @stevepeak.
+
+## Version 1.1.9
+
+- Fix `api.helper.get.is_delegated_inbox`, by @moodsey211.
+
+## Version 1.1.8
+
+- Fix incorrect variable name in GmailCache definition
+
+## Version 1.1.7
+
+- Fix for `api.tools.parse_attachment_url`.
+
+## Version 1.1.6
+
+- Better fix for `view_thread` event not triggeriong, by @cancan101.
+
+## Version 1.1.5
+
+- Improved parsing of embedded json data, by @onestep.
+- Tentative fix for `view_thread` event not triggeriong, by @cancan101.
+
+## Version 1.1.4
+
+- Fix subject-value in `api.observe.on("send_message")` event-data, by @cancan101.
+
+## Version 1.1.3
+
+- Even more fixes for `api.observe.on("send_message")` by @huksley.
+
+## Version 1.1.2
+
+- Try some fixes for `api.observe.on("send_message")`.
+
+## Version 1.1.1
+
+- More fixes for `api.new.get.email_data()` and `api.new.get.thread_data()`.
+
+## Version 1.1.0
+
+- First release to fix new XHR format in Gmail. This fixes
+ `api.new.get.email_data()` and `api.new.get.thread_data()`.
+
+## Version 1.0.23
+
+- Fix error in `insertion_observer()`.
+- Remove no longer working functions: `gmail.get.loggedin_accounts()`,
+ `gmail.get.manager_email()` and `gmail.get.delegated_to_email()`.
+
+## Version 1.0.22
+
+- Fix incompatibility with Mixmax extension. Thanks @DrParanoia!
+
+## Version 1.0.21
+
+- Various typescript type-improvements. Thanks again @cancan101!
+- Fix errors when trying to prefetch email-data. Once again, thanks to @cancan101!
+- Introduce new function `gmail.tools.add_more_send_option()`. Even more thanks to @cancan101!
+- Make `gmail.get.email_source_*()` handle new-style and old-style identifiers natively.
+
+## Version 1.0.20
+
+- Fix error in TypeScript type-definitions. No functional/runtime changes. Thanks @cancan101
+
+## Version 1.0.19
+
+- Fix compose button being duplicated when using `gmail.tools.add_compose_button` more than once.
+
+## Version 1.0.18
+
+- Fix parsing of attachments in emails form embedded JSON. Thanks @onestep!
+
+## Version 1.0.17
+
+- Fix ussyes with `gmail.dom.visible_messages()`. Thanks @mhatvan!
+
+## Version 1.0.16
+
+- Fix `gmail.observe.on("http_event")` and `gmail.observe.after("http_event")` triggers to receive all XHR requests.
+- Fix issue of `api.tools.parse_requests` mutating the `xhrParams` variable, causing stacked instances of `gmail-js` to not work as expected around XHR events. This closes [issue 662](https://github.com/KartikTalwar/gmail.js/issues/662).
+
+## Version 1.0.15
+
+- Fix issue with accessing to(), cc() and bcc() in compose-fields with
+ new Gmail "PeopleKit" UI. Thanks @huksley!
+
+## Version 1.0.14
+
+- Persist if a message is a draft during request parsing.
+
+## Version 1.0.13
+
+- Fix error in `gmail.get.localization()`, which should have been caught by CI.
+
+## Version 1.0.12
+
+- Fix error in `gmail.get.localization()`. This closes [issue 652](https://github.com/KartikTalwar/gmail.js/issues/652).
+
+## Version 1.0.11
+
+- Fix cursor when hovering over button created using `gmail.tools.add_compose_button`.
+
+## Version 1.0.10
+
+- Better attempt at fixing incorrect triggering of custom buttons created through GmailJS.
+
+## Version 1.0.9 - unpublished
+
+- Fix incorrect triggering of custom buttons created through GmailJS.
+
+## Version 1.0.8 - unpublished
+
+- Fix Firefox-compatibility issue in Gmail click-jack prevention.
+
+## Version 1.0.7 - unpublished
+
+- Fix issues with Gmail preventing click-events on buttons registered
+ thourgh GmailJS. Closes #648.
+
+## Version 1.0.6
+
+- Fix `gmail.compose.start_compose()`.
+
+## Version 1.0.5
+
+- Improve ergonomics of `gmail.dom.email()`. Support new email-id in constructor.
+
+## Version 1.0.4
+
+- Fix `gmail.check.is_inside_email()`
+
+## Version 1.0.3
+
+- Make `compose` cc() and bcc() methods force show cc and bcc-fields
+ before updating.
+
+## Version 1.0.2
+
+- Fix for `compose` to(), cc() and bcc() methods not updating
+ email correctly.
+
+## Version 1.0.1
+
+- Fix selector for start-compose button. Thanks @mikob!
+
+## Version 1.0.0
+
+- major improvements in populating the email-cache. Thanks @Fabi1Sc!
+ NOTE: requires changes to extension-loading. See README!
+- deprecate more old-style APIs
+
+## Version 0.9.9
+
+- add support for getting visible emails through DOM
+ (replaces api.get.visible_emails())
+
+## Version 0.9.8
+
+- add support for parsing sent email data in new Gmail.
+- add norwegian localizations.
+- fix attachment URLs in non-primary gmail accounts.
+- fix emails-property in gmail.new.get.thread_data().
+- fix incorrect email counts in gmail.get.unread_emails() and related functions.
+- add thread_id() function to DOM compose instances.
+
+## Version 0.9.7
+
+- fix issues with crash when invoked in cross-origin context.
+
+## Version 0.9.6
+
+- add support for closing compose-windows.
+- add event for `send_scheduled_message` event.
+
+## Version 0.9.5
+
+- Further API compatibility and ergonomics improvements.
+
+## Version 0.9.4
+
+- Make `api.new.get.email_id()` able to work with DOMEmail directly.
+
+## Version 0.9.3
+
+- Fix bug introduced in `api.new.get.email_data()` in version 0.9.2
+ when not providing email-id.
+
+## Version 0.9.2
+
+- Make `api.new.get.email_data()` handle legacy-style IDs when
+ present to improve compatibility. Creates console-warning when detected.
+
+## Version 0.9.1
+
+- Add ability to get new-style email-id directly from DOM element in
+ `api.new.get.email_id()`.
+
+## Version 0.9.0
+
+- Don't make attachment-detail compatibility harder than it needs to
+ be. Reuse old types.
+- Replace sender_address string with detailed from-field in new Gmail
+ EmailData-object.
+
+## Version 0.8.2
+
+- Fix wrong and missing type-annotations.
+- Add `content_html` property to `api.new.get.email_data()`.
+
+## Version 0.8.1
+
+- Add optional parameters to control button-text in `api.tools.add_modal_window()`.
+
+## Version 0.8.0
+
+- Introduce new `api.new.get.*` API for new Gmail only.
+- Enhanced XHR monitoring to provide email-data, based entirely on new data-layer.
+ (Provide 2019+ compatibility)
+
## Version 0.7.7
- Fix error in `api.get.displayed_email_data()` when conversation mode is off.
diff --git a/README.md b/README.md
index 150875cc..b35e8c5a 100755
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Gmail.js - JavaScript API for Gmail
-
+
[](https://www.npmjs.com/package/gmail-js)
### What Gmail.js is and isn't
@@ -18,6 +18,7 @@ It cannot be used server-side with Node, or from another web-app to interface wi
- Lots of API methods to work with gmail. See documentation below.
- Easy to use API. Data & DOM.
- Reasonably complete TypeScript-support.
+- Compatible with both WebExtension Manifest V2 and V3.
- Many methods are contextual and will work with whatever is on screen when no arguments are given.
- Obtain email data, react to event, etc. No need for OAuth!
- Main methods allow you to observe certain events with **`gmail.observe.on('lots_of_actions_here', callback())`** or similar **`gmail.observe.before(...)`** and **`gmail.observe.after(...)`**
@@ -32,42 +33,16 @@ npm install gmail-js
```
**Note:** Please ensure that Gmail.js is injected into the regular DOM.
-Gmail.js does not work as a content-script.
-
-For some ready to use examples/boilerplate repos, look no further:
-
-- **[GmailJS Node Boilerplate](https://github.com/josteink/gmailjs-node-boilerplate)** - Example for how to create a browser-extension using GmailJS and modern javascript with NodeJS and script-bundling for instant load-times.
-- **[GmailJS Legacy Boilerplate](https://github.com/KartikTalwar/gmail-chrome-extension-boilerplate)** - Example for how to create a browser-extension using traditional script-loading. (Requires less tooling, but is less reliable)
-
-### Content Security Policy
-
-Content Security Policy (CSP) will prevent direct injection. Please see the following repository to get around the policies. More details can also be found in issue [#75](https://github.com/KartikTalwar/gmail.js/issues/75)
-
-See the examples linked above for how to get around that.
-
-## Setup
-- **Gmail.js requires jQuery to work**
+Content-scripts which launch injected script must be configured with `"run_at": "document_start"`.
-### Quick Usage - Chrome Console
+It's recommended to split injected script to have only gmail.js load first because the size of the injected script impacts the loading time. Gmail.js must be injected and loaded before Gmail loads embedded data.
-
+Gmail.js does not work as a content-script.
-```js
-// {inject jquery.js} by copy pasting this in your console
-var jq = document.createElement('script');
-jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
-document.getElementsByTagName('body')[0].appendChild(jq);
-
-// {inject gmail.js} by copy pasting gmail.js contents or via url like jquery above
-// var Gmail = {.....} // paste gmail.js code here
-
-// start using!
-// you can also pass in a reference to jQuery upon init - Gmail(localJQuery)
-var gmail = Gmail();
-gmail.get.user_email();
-```
+For a ready to use example/boilerplate repo, look no further:
+- **[GmailJS Node Boilerplate](https://github.com/josteink/gmailjs-node-boilerplate)** - Example for how to create a browser-extension using GmailJS and modern javascript with NodeJS and script-bundling for instant load-times.
## Typescript
@@ -80,6 +55,14 @@ const gmail = new GmailFactory.Gmail() as Gmail;
// working on the gmail-object now provides type-safety.
````
+You will also have to import the types somewhere, like in a file called `types.d.ts` in your project:
+
+````typescript
+import "gmail-js";
+````
+
+
+
## Methods
### Summary (click for more info)
@@ -89,21 +72,17 @@ const gmail = new GmailFactory.Gmail() as Gmail;
- [gmail.get**.user_email()**](#gmailgetuser_email)
- [gmail.get**.manager_email()**](#gmailgetmanager_email)
-- [gmail.get**.visible_emails()**](#gmailgetvisible_emails)
-- [gmail.get**.visible_emails_async(callback)**](#gmailgetvisible_emailscallback)
-- [gmail.get**.selected_emails_data()**](#gmailgetselected_emails_data)
- [gmail.get**.current_page()**](#gmailgetcurrent_page)
-- [gmail.get**.thread_id()**](#gmailgetthread_id)
-- [gmail.get**.email_id()**](#gmailgetemail_id)
-- [gmail.get**.email_ids()**](#gmailgetemail_ids)
+
+- [gmail.get**.new.email_id()**](#gmailnewgetemail_id)
+- [gmail.get**.new.email_data()**](#gmailnewgetemail_dataidentifier)
+- [gmail.get**.new.thread_id()**](#gmailnewgetthread_id)
+- [gmail.get**.new.thread_data()**](#gmailnewgetthread_dataidentifier)
+
- [gmail.get**.email_subject()**](#gmailgetemail_subject)
- [gmail.get**.compose_ids()**](#gmailgetcompose_ids)
-- [gmail.get**.email_data(email_id=undefined)**](#gmailgetemail_dataemail_idundefined)
-- [gmail.get**.email_data_async(email_id=undefined, callback)**](#gmailgetemail_dataemail_idundefined-callback)
-- [gmail.get**.displayed_email_data()**](#gmailgetdisplayed_email_data)
-- [gmail.get**.displayed_email_data_async(callback)**](#gmailgetdisplayed_email_data_asynccallback)
-- [gmail.get**.email_source_async(email_id=undefined, callback, error_callback, preferBinary)**](#gmailgetemail_source_asyncemail_idundefined-callback-error_callback-preferBinaryfalse)
-- [gmail.get**.email_source_promise(email_id=undefined, preferBinary)**](#gmailgetemail_source_promiseemail_idundefined-preferBinaryfalse)
+- [gmail.get**.email_source_async(identifier=undefined, callback, error_callback, preferBinary)**](#gmailgetemail_source_asyncidentifierundefined-callback-error_callback-preferBinaryfalse)
+- [gmail.get**.email_source_promise(identifier=undefined, preferBinary)**](#gmailgetemail_source_promiseidentifierundefined-preferBinaryfalse)
- [gmail.get**.search_query()**](#gmailgetsearch_query)
- [gmail.get**.unread_emails()**](#gmailgetunread_emails)
- [gmail.get**.unread_inbox_emails()**](#gmailgetunread_emails)
@@ -119,6 +98,19 @@ const gmail = new GmailFactory.Gmail() as Gmail;
- [gmail.get**.beta()**](#gmailgetbeta)
- [gmail.get**.localization()**](#gmailgetlocalization)
+#### GET (deprecated methods)
+
+- [gmail.get**.thread_id()**](#gmailgetthread_id)
+- [gmail.get**.email_id()**](#gmailgetemail_id)
+- [gmail.get**.email_ids()**](#gmailgetemail_ids)
+- [gmail.get**.email_data(email_id=undefined)**](#gmailgetemail_datathread_idundefined)
+- [gmail.get**.email_data_async(email_id=undefined, callback)**](#gmailgetemail_data_asyncemail_idundefined-callback)
+- [gmail.get**.displayed_email_data()**](#gmailgetdisplayed_email_data)
+- [gmail.get**.displayed_email_data_async(callback)**](#gmailgetdisplayed_email_data_asynccallback)
+- [gmail.get**.selected_emails_data()**](#gmailgetselected_emails_data)
+- [gmail.get**.visible_emails()**](#gmailgetvisible_emails)
+- [gmail.get**.visible_emails_async(callback)**](#gmailgetvisible_emails_asynccallback)
+
#### CHECK
@@ -160,12 +152,6 @@ const gmail = new GmailFactory.Gmail() as Gmail;
#### OBSERVE
-It is considered best practice to wait for the gmail interface to be loaded before observing any XHR actions.
-```js
-gmail.observe.on("load", function(){
- //... now you can safely register other observers using gmail.observe.on
-});
-```
- [gmail.observe**.http_requests()**](#gmailobservehttp_requests)
- [gmail.observe**.actions()**](#gmailobserveactions)
@@ -186,7 +172,7 @@ gmail.observe.on("load", function(){
- **`mark_as_spam`** - When a conversation(s) is marked as spam
- **`mark_as_not_spam`** - When a conversation(s) is unchecked as spam
- **`label`** - When a conversation(s) get applied a label
- - **`archive`** - When a conversation(s) is archieved
+ - **`archive`** - When a conversation(s) is archived
- **`move_to_inbox`** - When a conversation(s) is moved to the inbox
- **`delete_forever`** - When a conversation(s) is deleted forever
- **`star`** - When a conversation(s) is starred
@@ -200,8 +186,9 @@ gmail.observe.on("load", function(){
- **`add_to_tasks`** - When an item is added to google tasks
- **`move_label`** - When a conversation(s) is moved to a label folder
- **`save_draft`** - When a draft is saved
- - **`discard_draft`** - When a draft is dicarded
- - **`send_message`** - When a message is sent
+ - **`discard_draft`** - When a draft is discarded
+ - **`send_message`** - When a message is sent (except scheduled messages)
+ - **`send_scheduled_message`** - When a message is scheduled for sending (but not actually sent)
- **`expand_categories`** - When a category is expanded from the left nav sidebar
- **`restore_message_in_thread`** - When a deleted message is restored inside a thread
- **`delete_label`** - When a label is deleted
@@ -227,6 +214,7 @@ These methods return the DOM data itself
- gmail.dom**.inboxes()**
- gmail.dom**.inbox_content()**
+- [gmail.dom**.visible_messages()**](#gmaildomvisiblemessages)
- gmail.dom**.email_subject()**
- gmail.dom**.email_body()**
- gmail.dom**.email_contents()**
@@ -235,8 +223,8 @@ These methods return the DOM data itself
- gmail.dom**.search_bar()**
- gmail.dom**.toolbar()**
- gmail.dom**.right_toolbar()**
-- gmail.dom**.compose()** - compose dom object - receives the DOM element for the compose window and provides methods to interact
-- gmail.dom**.composes()** - retrives an array of `gmail.dom.compose` objects representing any open compose windows
+- [gmail.dom**.compose()**](#gmaildomcomposecompose_el) - compose dom object - receives the DOM element for the compose window and provides methods to interact
+- gmail.dom**.composes()** - retrieves an array of `gmail.dom.compose` objects representing any open compose windows
- [gmail.dom**.email()**](#gmaildomemailemail_el-or-email_id) - email dom object - receives an email DOM element or email id for an email currently being viewed. Abstracts interaction with that email.
- [gmail.dom**.thread()**](#gmaildomthreadthread_el) - thread dom object - receives a conversation thread DOM element currently being viewed. Abstracts interaction with that thread.
@@ -264,7 +252,8 @@ These are some helper functions that the rest of the methods use. See source for
- gmail.tools**.toggle_minimize()**
- [gmail.tools**.add_toolbar_button(content_html, onclick_action, custom_style_class)**](#gmailtoolsadd_toolbar_buttoncontent_html-onclick_action-custom_style_class)
- [gmail.tools**.add_right_toolbar_button(content_html, onclick_action, custom_style_class)**](#gmailtoolsadd_right_toolbar_buttoncontent_html-onclick_action-custom_style_class)
-- [gmail.tools**.add_compose_button(compose_ref, content_html, onclick_action, custom_style_class)**](#gmailtoolsadd_toolbar_buttoncompose_ref-content_html-onclick_action-custom_style_class)
+- [gmail.tools**.add_compose_button(compose_ref, content_html, onclick_action, custom_style_class)**](#gmailtoolsadd_compose_buttoncompose_ref-content_html-onclick_action-custom_style_class)
+- [gmail.tools**.add_more_send_option(composeWindow, buttonText, onClickFunction, styleClass, imgClass)**](#gmailtoolsadd_more_send_optioncomposewindow-buttontext-onclickfunction-styleclass-imgclass)
- [gmail.tools**.add_modal_window(title, content_html, onClickOk, onClickCancel, onClickClose)**](#gmailtoolsadd_modal_windowtitle-content_html-onClickOk-onClickCancel-onClickClose)
- [gmail.tools**.remove_modal_window()**](#gmailtoolsremove_modal_window)
@@ -287,208 +276,151 @@ These are some of the variables that are tracked and kept in memory while the re
### Details
-#### gmail.get.visible_emails()
-Returns a list of emails from the server that are currently visible in the inbox view. The data does not come from the DOM
+#### gmail.new.get.email_id()
-```json
-[{"id": "1425a3693a4c45d0",
- "title": "What if video games were real? On YouTube",
- "excerpt": "View email in a web browser Header Super Mario Brothers Parkour by Warialasky Super Mario Brothers",
- "time": "Fri, Nov 15, 2013 at 12:23 AM",
- "sender": "noreply@youtube.com",
- "attachment": "",
- "labels": ["^all", "^i", "^smartlabel_social", "^unsub"]}]
-```
+Obtains the new-style email-ID from the email currently on screen.
+Extracted via DOM.
-#### gmail.get.visible_emails(async)
+This ID can only be used by `gmail.new.get.*`-functions.
-Does the same as above but accepts a callback function
+Can be provided email-element from HTML DOM, or Gmail DOMEmail object
+to look up specific email ID.
-#### gmail.get.selected_emails_data()
+#### gmail.new.get.thread_id()
-Returns a list of object representation from emails that are currently **selected** in the inbox view.
-The data does not come from the DOM
+Obtains the new-style thread-ID from the email currently on screen.
+Extracted via DOM.
-```json
-[{
- "thread_id":"141d44da39d6caf8",
- "first_email": "141d44da39d6caf9",
- "last_email": "141d44da39d6caf9",
- "total_emails": 1,
- "total_threads": ["141d44da39d6caf8"],
- "people_involved": [
- ["Kartik Talwar", "hi@kartikt.com"],
- ["California", "california@gmail.com"]
- ],
- "subject": "test",
- "threads": {
- "141d44da39d6caf8": {
- "reply_to_id": "",
- "reply_to": "replytome@gmail.com",
- "is_deleted" : false,
- "from": "California",
- "to" : ["hi@kartikt.com"],
- "cc" : [],
- "bcc" : [],
- "from_email": "california@gmail.com",
- "timestamp": 1382246359000,
- "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
- "content_plain": "another test",
- "subject": "test",
- "content_html": "
another test
\n"
- }
- }
-},{
- "thread_id":"141d44da39d6caf8",
- "first_email": "141d44da39d6caf8",
- "last_email": "141d44da39d6caf8",
- "total_emails": 1,
- "total_threads": ["141d44da39d6caf8"],
- "people_involved": [
- ["Kartik Talwar", "hi@kartikt.com"],
- ["California", "california@gmail.com"]
- ],
- "subject": "test",
- "threads": {
- "141d44da39d6caf8": {
- "reply_to_id": "",
- "reply_to": null,
- "is_deleted" : false,
- "from": "California",
- "to" : ["hi@kartikt.com"],
- "cc" : [],
- "bcc" : [],
- "from_email": "california@gmail.com",
- "timestamp": 1382246359000,
- "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
- "content_plain": "another test",
- "subject": "test",
- "content_html": "another test
\n"
- }
- }
-}]
-```
+This ID can only be used by `gmail.new.get.*`-functions.
-#### gmail.get.email_data(thread_id=undefined)
+#### gmail.new.get.email_data(identifier)
-Returns an object representation of the opened email contents and metadata. It takes the optional thread_id parameter where
-the data for the specified thread is returned instead of the email-thread currently visible in the dom.
+Returns a data-object for the requested email, if found in the
+email-cache.
+
+`identifier` must be an object or string which uniquely identifies
+an email:
+
+- new-style email-id
+- legacy-style email-id (will cause warning)
+- DomEmail instance
+- EmailData instance
+
+If no email-data can be found in Gmail.JS email-cache,
+`null` or `undefined` is returned instead.
+
+This method returns immediately, uses no XHR, and has no
+async-equivalent.
+
+Please note: Email-data is intercepted and stored in the cache
+only when Gmail itself has requested or used and email.
+
+This typically happens when loading a label (pre-loading all emails in
+view) or when navigating to view a full thread.
+
+That means that calling the same method later may return data even if
+the first invocation returned `null`.
-`thread_id` is added for updated gmail thread behaviour which adds support for emails created in [inbox](https://inbox.google.com). first_email remains as the first message in the thread.
```json
{
- "thread_id":"141d44da39d6caf8",
- "first_email": "141d44da39d6caf8",
- "last_email": "141d44da39d6caf8",
- "total_emails": 1,
- "total_threads": ["141d44da39d6caf8"],
- "people_involved": [
- ["Kartik Talwar", "hi@kartikt.com"],
- ["California", "california@gmail.com"]
+ "id": "msg-f:1581064946762017791",
+ "legacy_email_id": "15f1123136926bff",
+ "thread_id": "thread-f:1581064946762017791",
+ "smtp_id": "<87zi8wmmhw.fsf@gmail.com>",
+ "subject": "[PATCH] Flymake support for C/C++",
+ "timestamp": 1507821032297,
+ "content_html": "Hi,
\n
\nHere's a proposal for supporting Flymake in C/C++. This patch...",
+ "date": "2017-10-12T15:10:32.297Z",
+ "from": {
+ "address": "joaotavora@gmail.com",
+ "name": ""
+ },
+ "to": [
+ {
+ "address": "emacs-devel@gnu.org"
+ }
],
- "subject": "test",
- "threads": {
- "141d44da39d6caf8": {
- "reply_to_id": "",
- "reply_to": "replytome@gmail.com",
- "is_deleted" : false,
- "from": "California",
- "to" : ["hi@kartikt.com"],
- "cc" : [],
- "bcc" : [],
- "from_email": "california@gmail.com",
- "timestamp": 1382246359000,
- "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
- "content_plain": "another test",
- "subject": "test",
- "content_html": "another test
\n",
- "attachments": [
- "some_file.pdf"
- ],
- "attachments_details": [
- {
- "attachment_id": "0.1",
- "name": "some_file.pdf",
- "size": 11235,
- "type": "application/pdf",
- "url": "https://mail.google.com/u/0/?ui=......"
- }]
+ "cc": [
+ {
+ "address": "acm@muc.de"
+ },
+ {
+ "address": "eliz@gnu.org"
}
- }
+ ],
+ "bcc": [],
+ "attachments": [
+ {
+ "attachment_id": "0.1",
+ "name": "0001-Add-a-Flymake-backend-for-C.patch",
+ "type": "application/x-patch",
+ "url": "https://mail.google.com/mail/?ui=2&ik=94da28fb67&attid=0.1&permmsgid=msg-f:1581064946762017791&th=15f1123136926bff&view=att&zw",
+ "size": 11225
+ }
+ ]
}
```
-#### gmail.get.email_data_async(email_id=undefined, callback)
+#### gmail.new.get.thread_data(identifier)
+Returns a data-object for the requested email-thread, if found in the
+email-cache.
-Does the same as above but accepts a callback function
+`identifier` must be an object or string which uniquely identifies
+a thread:
+- a new-style thread-id
+- new-style email-id
+- legacy-style email-id (will cause warning)
+- DomEmail instance
+- DomThread instance
+- EmailData instance
-#### gmail.get.displayed_email_data()
+If no thread-data can be found in Gmail.JS email-cache,
+`null` or `undefined` is returned instead.
-Returns an object representation of the emails that are being displayed.
+This method returns immediately, uses no XHR, and has no
+async-equivalent.
-```json
-{
- "thread_id":"141d44da39d6caf8",
- "first_email": "145881e7a8befff6",
- "last_email": "145881e7a8befff6",
- "total_emails": 1,
- "total_threads": ["145881e7a8befff6"],
- "people_involved": [
- ["Kartik Talwar", "hi@kartikt.com"],
- ["California", "california@gmail.com"]
- ],
- "subject": "test",
- "threads": {
- "145881e7a8befff6": {
- "reply_to_id": "",
- "reply_to": "replytome@gmail.com",
- "is_deleted" : false,
- "from": "California",
- "to" : ["hi@kartikt.com"],
- "cc" : [],
- "bcc" : [],
- "from_email": "california@gmail.com",
- "timestamp": 1382246359000,
- "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
- "content_plain": "another test",
- "subject": "test",
- "content_html": "another test
\n",
- "attachments": [
- "some_file.pdf"
- ],
- "attachments_details": [
- {
- "attachment_id": "0.1",
- "name": "some_file.pdf",
- "size": 11235,
- "type": "application/pdf",
- "url": "https://mail.google.com/u/0/?ui=......"
- }]
- }
- }
-}
+Please note: Email-data is intercepted and stored in the cache
+only when Gmail itself has requested or used and email.
-```
+This typically happens when loading a label (pre-loading all emails in
+view) or when navigating to view a full thread.
-#### gmail.get.displayed_email_data_async(callback)
+That means that calling the same method later may return data even if
+the first invocation returned `null`.
-Does the same as above but accepts a callback function.
+```json
+{
+ "thread_id": "thread-f:1581064946762017791",
+ "emails": [...email_data elements...]
+}
+```
-#### gmail.get.email_source(email_id=undefined)
+#### gmail.get.email_source(identifier=undefined)
Deprecated function. Will be removed. Migrate to
`gmail.get.email_source_async` or `gmail.get.email_source_promise`
instead.
-#### gmail.get.email_source_async(email_id=undefined, callback, error_callback, preferBinary=false)
+#### gmail.get.email_source_async(identifier=undefined, callback, error_callback, preferBinary=false)
-Retrieves raw MIME message source from the gmail server for the specified email id. It takes the optional email_id parameter where
-the data for the specified id is returned instead of the email currently visible in the dom
+Retrieves raw MIME message source from the gmail server for the
+specified email identifier.
+
+`identifier` must be an object or string which uniquely identifies
+an email:
+
+- new-style email-id
+- legacy-style email-id (will cause warning)
+- DomEmail instance
+- EmailData instance
+
+If not specified, current email will be resolved automatically.
By default, once retrieved the resulting data will be passed to
`callback` in text-format. **This may corrupt the actual email
@@ -502,7 +434,7 @@ format and do your own decoding inside your own MIME-parser.
To get the email-source in binary form, you must set the
`preferBinary`-parameter to `true`.
-#### gmail.get.email_source_promise(email_id=undefined, preferBinary=false)
+#### gmail.get.email_source_promise(identifier=undefined, preferBinary=false)
Does the same as above but implements it using ES6 promises.
@@ -565,31 +497,6 @@ Returns the opened email's subject from the DOM
```
-#### gmail.get.thread_id()
-
-Gets current email-thread's ID.
-
-This can be used together with `gmail.get.email_data()` to obtain
-individual email IDs.
-
-
-#### gmail.get.email_id()
-
-Same as `gmail.get.thread_id()`, but kept for compatibilty.
-Using this method generates a warning!
-
-```js
-"141de25dc0b48e4f"
-```
-
-#### gmail.get.email_ids()
-
-Returns a list of email IDs for each thread in the conversation
-
-```js
-["141de25dc0b48e4f"]
-```
-
### gmail.get.compose_ids()
Returns the latest/last email id of emails that have been saved as drafts (currently open)
@@ -675,6 +582,10 @@ Returns `True` if the user is running Gmail with the new 2018 data-layer `False`
Returns `True` if the user is running Gmail with the new 2018 GUI `False` otherwise
+#### gmail.check.is_peoplekit_compose(composeElement)
+
+Returns `True` if the compose UI uses new UI as announced [here](https://workspaceupdates.googleblog.com/2021/10/visual-updates-for-composing-email-in-gmail.html) `False` otherwise
+
#### gmail.check.is_thread()
Returns `True` if the conversation is threaded `False` otherwise
@@ -689,7 +600,7 @@ Returns `True` if user has multiple inbox lab enabled, `False` otherwise
#### gmail.check.is_horizontal_split()
-Returns `True` if the pane split mode is horiontal `False` otherwise
+Returns `True` if the pane split mode is horizontal `False` otherwise
#### gmail.check.are_shortcuts_enabled()
@@ -806,7 +717,7 @@ The items contain the sent requested parameterized data
#### gmail.observe.actions()
Similar to `gmail.observe.http_requests()` this keeps track of the last 10 gmail actions (vs all http requests).
-Actions here correspond to things like clicking refres, archiving, deleting, starring etc.
+Actions here correspond to things like clicking refresh, archiving, deleting, starring etc.
#### gmail.observe.on(action, callback)
@@ -820,7 +731,7 @@ Your callback will be fired directly after Gmail's XMLHttpRequest has been sent
**Available Actions**
- - **http_event** - When gmail any CRUD operation happens on gmail
+ - **http_event** - When gmail any XHR CRUD operation happens on gmail
- **poll** - When gmail automatically polls the server to check for new emails every few seconds
- **new_email** - When a new email appears in the inbox
- **open_email** - When an email is opened from the inbox view
@@ -832,7 +743,7 @@ Your callback will be fired directly after Gmail's XMLHttpRequest has been sent
- **mark_as_spam** - When a conversation(s) is marked as spam
- **mark_as_not_spam** - When a conversation(s) is unchecked as spam
- **label** - When a conversation(s) get applied a label
- - **archive** - When a conversation(s) is archieved
+ - **archive** - When a conversation(s) is archived
- **move_to_inbox** - When a conversation(s) is moved to the inbox
- **delete_forever** - When a conversation(s) is deleted forever
- **star** - When a conversation(s) is starred
@@ -846,14 +757,15 @@ Your callback will be fired directly after Gmail's XMLHttpRequest has been sent
- **add_to_tasks** - When an item is added to google tasks
- **move_label** - When a conversation(s) is moved to a label folder
- **save_draft** - When a draft is saved
- - **discard_draft** - When a draft is dicarded
- - **send_message** - When a message is sent
+ - **discard_draft** - When a draft is discarded
+ - **send_message** - When a message is sent (except scheduled messages)
+ - **send_scheduled_message** - When a message is scheduled for sending (but not actually sent)
- **expand_categories** - When a category is expanded from the left nav sidebar
- **restore_message_in_thread** - When a deleted message is restored inside a thread
- **delete_label** - When a label is deleted
- **show_newly_arrived_message** - When inside an email and a new email arrives in the thread
-The on method also supports observering specific DOM events in the Gmail Interface (for example when a new compose window is opened). These are only available via the `on` method (not the `before` or `after` methods).
+The on method also supports observing specific DOM events in the Gmail Interface (for example when a new compose window is opened). These are only available via the `on` method (not the `before` or `after` methods).
**Available DOM Actions/Observers**
@@ -861,12 +773,12 @@ The on method also supports observering specific DOM events in the Gmail Interfa
- **compose** - When a new compose window opens, or a message is replied to or forwarded
- **compose_cancelled** - When an existing compose window is closed.
- **recipient_change** - When the recipient (to, cc or bcc) is changed when composing a new email or replying/forwarding an email
- - **view_thread** - When a new coversation thread is opened
+ - **view_thread** - When a new conversation thread is opened
- **view_email** - When an individual email is loaded within a thread (also fires when thread loads displaying the latest email)
- **load_email_menu** - When the dropdown menu next to the reply button is clicked
```js
-gmail.observe.on("http_event", function(params) {
+gmail.observe.on("http_event", function(params, xhr) {
console.log("url data:", params);
})
@@ -966,6 +878,10 @@ gmail.observe.on("send_message", function(url, body, data, xhr) {
console.log("url:", url, 'body', body, 'email_data', data, 'xhr', xhr);
})
+gmail.observe.on("send_scheduled_message", function(url, body, data, xhr) {
+ console.log("url:", url, 'body', body, 'email_data', data, 'xhr', xhr);
+})
+
gmail.observe.on("expand_categories", function(url, body, data, xhr) {
console.log("url:", url, 'body', body, 'expanded_data', data, 'xhr', xhr);
})
@@ -1106,7 +1022,7 @@ Simple:
Complex:
- action - the name of the new DOM observer
- - args - an object containin properties for each of the supported DOM observer configuration agruments:
+ - args - an object containing properties for each of the supported DOM observer configuration arguments:
- class - the class of an inserted DOM element that identifies that this action should be triggered
- selector - if you need to match more than just the className of a specific element to indicate a match, you can use this selector for further checking (uses element.is(selector) on matched element). E.g. if there are multiple elements with a class indicating an observer should fire, but you only want it to fire on a specific id, then you would use this
- sub_selector - if specified, we do a jquery element.find for the passed selector on the inserted element and ensure we can find a match
@@ -1126,10 +1042,73 @@ gmail.observe.on('compose_email_select', function(match) {
```
+### gmail.dom.visible_messages()
+Returns basic data for all the messages currently visible in the messages view. Taken from the DOM.
+
+```json
+[
+{
+ "summary": "Hey Bill",
+ "from": {
+ "email": "joe@gmail.com",
+ "name": "Joe",
+ },
+ "$el": tr#:9b.zA.zE.inboxsdk__thread_row,
+ "thread_id": "thread-f:1628504557508152478",
+ "legacy_email_id": undefined,
+},
+{
+ "summary": "The best of Gmail, wherever you are",
+ "from": {
+ "name": "Gmail",
+ "email": "mail-noreply@google.com"
+ },
+ "$el": tr#:9b.zA.zE.inboxsdk__thread_row,
+ "thread_id": "#thread-f:1634069952006597946"
+ "legacy_email_id": undefined,
+},
+]
+```
+
+
### gmail.dom.compose(compose_el)
-An object used to abstract interation with a compose popup
+An object used to abstract interaction with a compose popup.
+Represents a compose window in the DOM and provides a bunch of methods and properties to access & interact with the window.
+
+Expects a jQuery DOM element for the compose div.
+
+```javascript
+// you can use an observer to retrieve a compose object
+gmail.observe.on('compose', function(compose, composeType) {
+ // compose type can be one of "reply" | "forward" | "compose"
+ console.log('Compose object:', compose, 'compose type:', composeType);
+});
+```
+Compose methods:
+
+- **.id()** - retrieve the compose id
+- **.email_id()** - retrieve the draft email id
+- **.is_inline()** - is this compose instance inline (as with reply & forwards) or a popup (as with a new compose)
+- **.type()** - retrieve compose type - reply / forward / compose (new)
+- **.recipients(options)** - retrieves `to`, `cc`, `bcc` and returns them in a hash of arrays.
+ Options:
+ - *.type* - string `to`, `cc`, or `bcc` to check a specific one
+ - *.flat* - boolean if `true` will just return an array of all recipients instead of splitting out into to, cc, and bcc
+- **.to()** - retrieve the current `to` recipients
+- **.cc()** - retrieve the current `cc` recipients
+- **.bcc()** - retrieve the current `bcc` recipients
+- **.subject(subject)** - get/set the current subject
+- **.from()** - get the from email, if user only has one email account they can send from, returns that email address
+- **.body(body)** - get/set the email body
+- **.attachments()** - get the email attachments
+- **.send()** - triggers the same action as clicking the "send" button would do.
+- **.find(selector)** - map find through to jquery element
+- **.close()** - close compose window
+- **.dom(lookup)** - retrieve preconfigured dom elements for this compose window.
+ Lookup can be one of `'to' | 'cc' | 'bcc' | 'id' | 'draft' | 'subject' | 'subjectbox'
+ | 'all_subjects' | 'body' | 'quoted_reply' | 'reply' | 'forward' | 'from' | 'send_button' | 'show_cc' | 'show_bcc'`
### gmail.dom.email(email_el or email_id)
@@ -1303,6 +1282,18 @@ gmail.tools.add_compose_button(compose_ref, 'content_html', function() {
}, 'Custom Style Classes');
```
+#### gmail.tools.add_more_send_option(composeWindow, buttonText, onClickFunction, styleClass, imgClass)
+
+Add button to "more send options" menu.
+You can use gmail.dom.composes() to get compose reference.
+
+```js
+var compose_ref = gmail.dom.composes()[0];
+gmail.tools.add_more_send_option(compose_ref, 'buttonText', function() {
+ // Code here
+}, 'Custom Style Classes', 'imgClass');
+```
+
#### gmail.tools.add_attachment_button(attachment_ref, content_html, customCssClass, tooltip, onclick_action)
Add a button to an attachment in email-view.
@@ -1367,6 +1358,247 @@ Show/Hide compose window ```gmail.tools.toggle_minimize```.
gmail.tools.toggle_minimize
```
+### Details - Deprecated methods
+
+#### gmail.get.thread_id()
+
+**Note: This method can only be used with other deprecated methods,
+and is itself deprecated. Use `gmail.new.get.thread_id()` instead.**
+
+Gets current email-thread's ID.
+
+This can be used together with `gmail.get.email_data()` to obtain
+individual email IDs.
+
+
+#### gmail.get.email_id()
+
+**Note: This method can only be used with other deprecated methods,
+and is itself deprecated. Use `gmail.new.get.email_id()` instead.**
+
+Same as `gmail.get.thread_id()`, but kept for compatibility.
+Using this method generates a warning!
+
+```js
+"141de25dc0b48e4f"
+```
+
+#### gmail.get.email_ids()
+
+**Note: This method can only be used with other deprecated methods,
+and is itself deprecated. Use `gmail.new.get.thread_id()` and
+`gmail.new.get.thread_data()` instead.**
+
+Returns a list of email IDs for each thread in the conversation
+
+```js
+["141de25dc0b48e4f"]
+```
+
+#### gmail.get.visible_emails()
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Migrate to `gmail.new.get.*`-API instead.**
+
+Returns a list of emails from the server that are currently visible in the inbox view. The data does not come from the DOM
+
+```json
+[{"id": "1425a3693a4c45d0",
+ "title": "What if video games were real? On YouTube",
+ "excerpt": "View email in a web browser Header Super Mario Brothers Parkour by Warialasky Super Mario Brothers",
+ "time": "Fri, Nov 15, 2013 at 12:23 AM",
+ "sender": "noreply@youtube.com",
+ "attachment": "",
+ "labels": ["^all", "^i", "^smartlabel_social", "^unsub"]}]
+```
+
+#### gmail.get.visible_emails_async(callback)
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Migrate to `gmail.new.get.*`-API instead.**
+
+Does the same as above but accepts a callback function
+
+#### gmail.get.selected_emails_data()
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Migrate to `gmail.new.get.*`-API instead.**
+
+Returns a list of object representation from emails that are currently **selected** in the inbox view.
+The data does not come from the DOM
+
+```json
+[{
+ "thread_id":"141d44da39d6caf8",
+ "first_email": "141d44da39d6caf9",
+ "last_email": "141d44da39d6caf9",
+ "total_emails": 1,
+ "total_threads": ["141d44da39d6caf8"],
+ "people_involved": [
+ ["Kartik Talwar", "hi@kartikt.com"],
+ ["California", "california@gmail.com"]
+ ],
+ "subject": "test",
+ "threads": {
+ "141d44da39d6caf8": {
+ "reply_to_id": "",
+ "reply_to": "replytome@gmail.com",
+ "is_deleted" : false,
+ "from": "California",
+ "to" : ["hi@kartikt.com"],
+ "cc" : [],
+ "bcc" : [],
+ "from_email": "california@gmail.com",
+ "timestamp": 1382246359000,
+ "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
+ "content_plain": "another test",
+ "subject": "test",
+ "content_html": "another test
\n"
+ }
+ }
+},{
+ "thread_id":"141d44da39d6caf8",
+ "first_email": "141d44da39d6caf8",
+ "last_email": "141d44da39d6caf8",
+ "total_emails": 1,
+ "total_threads": ["141d44da39d6caf8"],
+ "people_involved": [
+ ["Kartik Talwar", "hi@kartikt.com"],
+ ["California", "california@gmail.com"]
+ ],
+ "subject": "test",
+ "threads": {
+ "141d44da39d6caf8": {
+ "reply_to_id": "",
+ "reply_to": null,
+ "is_deleted" : false,
+ "from": "California",
+ "to" : ["hi@kartikt.com"],
+ "cc" : [],
+ "bcc" : [],
+ "from_email": "california@gmail.com",
+ "timestamp": 1382246359000,
+ "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
+ "content_plain": "another test",
+ "subject": "test",
+ "content_html": "another test
\n"
+ }
+ }
+}]
+```
+
+#### gmail.get.email_data(thread_id=undefined)
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Use `gmail.new.get.email_data()` and `gmail.new.get.thread_data()` instead!**
+
+Returns an object representation of the opened email contents and metadata. It takes the optional thread_id parameter where
+the data for the specified thread is returned instead of the email-thread currently visible in the dom.
+
+`thread_id` is added for updated gmail thread behaviour which adds support for emails created in [inbox](https://inbox.google.com). first_email remains as the first message in the thread.
+
+```json
+{
+ "thread_id":"141d44da39d6caf8",
+ "first_email": "141d44da39d6caf8",
+ "last_email": "141d44da39d6caf8",
+ "total_emails": 1,
+ "total_threads": ["141d44da39d6caf8"],
+ "people_involved": [
+ ["Kartik Talwar", "hi@kartikt.com"],
+ ["California", "california@gmail.com"]
+ ],
+ "subject": "test",
+ "threads": {
+ "141d44da39d6caf8": {
+ "reply_to_id": "",
+ "reply_to": "replytome@gmail.com",
+ "is_deleted" : false,
+ "from": "California",
+ "to" : ["hi@kartikt.com"],
+ "cc" : [],
+ "bcc" : [],
+ "from_email": "california@gmail.com",
+ "timestamp": 1382246359000,
+ "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
+ "content_plain": "another test",
+ "subject": "test",
+ "content_html": "another test
\n",
+ "attachments": [
+ "some_file.pdf"
+ ],
+ "attachments_details": [
+ {
+ "attachment_id": "0.1",
+ "name": "some_file.pdf",
+ "size": 11235,
+ "type": "application/pdf",
+ "url": "https://mail.google.com/u/0/?ui=......"
+ }]
+ }
+ }
+}
+```
+
+#### gmail.get.email_data_async(email_id=undefined, callback)
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Use `gmail.new.get.email_data()` and `gmail.new.get.thread_data()` instead!**
+
+Does the same as above but accepts a callback function.
+
+
+#### gmail.get.displayed_email_data()
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Migrate to `gmail.new.get.*`-API instead.**
+
+Returns an object representation of the emails that are being displayed.
+
+```json
+{
+ "thread_id":"141d44da39d6caf8",
+ "first_email": "145881e7a8befff6",
+ "last_email": "145881e7a8befff6",
+ "total_emails": 1,
+ "total_threads": ["145881e7a8befff6"],
+ "people_involved": [
+ ["Kartik Talwar", "hi@kartikt.com"],
+ ["California", "california@gmail.com"]
+ ],
+ "subject": "test",
+ "threads": {
+ "145881e7a8befff6": {
+ "reply_to_id": "",
+ "reply_to": "replytome@gmail.com",
+ "is_deleted" : false,
+ "from": "California",
+ "to" : ["hi@kartikt.com"],
+ "cc" : [],
+ "bcc" : [],
+ "from_email": "california@gmail.com",
+ "timestamp": 1382246359000,
+ "datetime": "Sun, Nov 20, 2013 at 1:19 AM",
+ "content_plain": "another test",
+ "subject": "test",
+ "content_html": "another test
\n",
+ "attachments": [
+ "some_file.pdf"
+ ],
+ "attachments_details": [
+ {
+ "attachment_id": "0.1",
+ "name": "some_file.pdf",
+ "size": 11235,
+ "type": "application/pdf",
+ "url": "https://mail.google.com/u/0/?ui=......"
+ }]
+ }
+ }
+}
+
+```
+
+#### gmail.get.displayed_email_data_async(callback)
+
+**DEPRECATED! This function relies on XHR-invocation against a deprecated Gmail API and is is very likely to fail. Migrate to `gmail.new.get.*`-API instead.**
+
+Does the same as above but accepts a callback function.
+
## Author and Licensing
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 00000000..ad1f31e9
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,194 @@
+/*
+ * For a detailed explanation regarding each configuration property, visit:
+ * https://jestjs.io/docs/configuration
+ */
+
+module.exports = {
+ // All imported modules in your tests should be mocked automatically
+ // automock: false,
+
+ // Stop running tests after `n` failures
+ // bail: 0,
+
+ // The directory where Jest should store its cached dependency information
+ // cacheDirectory: "/tmp/jest_rs",
+
+ // Automatically clear mock calls, instances, contexts and results before every test
+ // clearMocks: false,
+
+ // Indicates whether the coverage information should be collected while executing the test
+ collectCoverage: true,
+
+ // An array of glob patterns indicating a set of files for which coverage information should be collected
+ // collectCoverageFrom: undefined,
+
+ // The directory where Jest should output its coverage files
+ coverageDirectory: "coverage",
+
+ // An array of regexp pattern strings used to skip coverage collection
+ // coveragePathIgnorePatterns: [
+ // "/node_modules/"
+ // ],
+
+ // Indicates which provider should be used to instrument code for coverage
+ coverageProvider: "v8",
+
+ // A list of reporter names that Jest uses when writing coverage reports
+ // coverageReporters: [
+ // "json",
+ // "text",
+ // "lcov",
+ // "clover"
+ // ],
+
+ // An object that configures minimum threshold enforcement for coverage results
+ // coverageThreshold: undefined,
+
+ // A path to a custom dependency extractor
+ // dependencyExtractor: undefined,
+
+ // Make calling deprecated APIs throw helpful error messages
+ // errorOnDeprecated: false,
+
+ // The default configuration for fake timers
+ // fakeTimers: {
+ // "enableGlobally": false
+ // },
+
+ // Force coverage collection from ignored files using an array of glob patterns
+ // forceCoverageMatch: [],
+
+ // A path to a module which exports an async function that is triggered once before all test suites
+ // globalSetup: undefined,
+
+ // A path to a module which exports an async function that is triggered once after all test suites
+ // globalTeardown: undefined,
+
+ // A set of global variables that need to be available in all test environments
+ // globals: {},
+
+ // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
+ // maxWorkers: "50%",
+
+ // An array of directory names to be searched recursively up from the requiring module's location
+ // moduleDirectories: [
+ // "node_modules"
+ // ],
+
+ // An array of file extensions your modules use
+ // moduleFileExtensions: [
+ // "js",
+ // "mjs",
+ // "cjs",
+ // "jsx",
+ // "ts",
+ // "tsx",
+ // "json",
+ // "node"
+ // ],
+
+ // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
+ // moduleNameMapper: {},
+
+ // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
+ // modulePathIgnorePatterns: [],
+
+ // Activates notifications for test results
+ // notify: false,
+
+ // An enum that specifies notification mode. Requires { notify: true }
+ // notifyMode: "failure-change",
+
+ // A preset that is used as a base for Jest's configuration
+ // preset: undefined,
+
+ // Run tests from one or more projects
+ // projects: undefined,
+
+ // Use this configuration option to add custom reporters to Jest
+ // reporters: undefined,
+
+ // Automatically reset mock state before every test
+ // resetMocks: false,
+
+ // Reset the module registry before running each individual test
+ // resetModules: false,
+
+ // A path to a custom resolver
+ // resolver: undefined,
+
+ // Automatically restore mock state and implementation before every test
+ // restoreMocks: false,
+
+ // The root directory that Jest should scan for tests and modules within
+ // rootDir: undefined,
+
+ // A list of paths to directories that Jest should use to search for files in
+ // roots: [
+ // ""
+ // ],
+
+ // Allows you to use a custom runner instead of Jest's default test runner
+ // runner: "jest-runner",
+
+ // The paths to modules that run some code to configure or set up the testing environment before each test
+ // setupFiles: [],
+
+ // A list of paths to modules that run some code to configure or set up the testing framework before each test
+ // setupFilesAfterEnv: [],
+
+ // The number of seconds after which a test is considered as slow and reported as such in the results.
+ // slowTestThreshold: 5,
+
+ // A list of paths to snapshot serializer modules Jest should use for snapshot testing
+ // snapshotSerializers: [],
+
+ // The test environment that will be used for testing
+ // testEnvironment: "jest-environment-node",
+
+ // Options that will be passed to the testEnvironment
+ // testEnvironmentOptions: {},
+
+ // Adds a location field to test results
+ // testLocationInResults: false,
+
+ // The glob patterns Jest uses to detect test files
+ testMatch: [
+ "**/test/**/test.*.js",
+ ],
+
+ // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
+ // testPathIgnorePatterns: [
+ // "/node_modules/"
+ // ],
+
+ // The regexp pattern or array of patterns that Jest uses to detect test files
+ // testRegex: [],
+
+ // This option allows the use of a custom results processor
+ // testResultsProcessor: undefined,
+
+ // This option allows use of a custom test runner
+ // testRunner: "jest-circus/runner",
+
+ // A map from regular expressions to paths to transformers
+ // transform: undefined,
+
+ // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
+ // transformIgnorePatterns: [
+ // "/node_modules/",
+ // "\\.pnp\\.[^\\/]+$"
+ // ],
+
+ // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
+ // unmockedModulePathPatterns: undefined,
+
+ // Indicates whether each individual test should be reported during the run
+ // verbose: undefined,
+
+ // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
+ // watchPathIgnorePatterns: [],
+
+ // Whether to use watchman for file crawling
+ // watchman: true,
+};
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..38498742
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,5296 @@
+{
+ "name": "gmail-js",
+ "version": "1.1.14",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "gmail-js",
+ "version": "1.1.14",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/jquery": "^3.5.14",
+ "eslint": "^8.23.1",
+ "jest": "^29.5.0",
+ "jest-junit": "^16.0.0",
+ "jsdom": "^20.0.0",
+ "typescript": "^4.8.3"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
+ "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.24.7",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.24.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz",
+ "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.24.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz",
+ "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.24.7",
+ "@babel/generator": "^7.24.9",
+ "@babel/helper-compilation-targets": "^7.24.8",
+ "@babel/helper-module-transforms": "^7.24.9",
+ "@babel/helpers": "^7.24.8",
+ "@babel/parser": "^7.24.8",
+ "@babel/template": "^7.24.7",
+ "@babel/traverse": "^7.24.8",
+ "@babel/types": "^7.24.9",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.24.10",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz",
+ "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.9",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz",
+ "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.24.8",
+ "@babel/helper-validator-option": "^7.24.8",
+ "browserslist": "^4.23.1",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
+ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
+ "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
+ "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
+ "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.24.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz",
+ "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.24.7",
+ "@babel/helper-module-imports": "^7.24.7",
+ "@babel/helper-simple-access": "^7.24.7",
+ "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz",
+ "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
+ "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
+ "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
+ "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
+ "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz",
+ "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz",
+ "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.24.7",
+ "@babel/types": "^7.24.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
+ "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.24.7",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz",
+ "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz",
+ "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz",
+ "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.24.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
+ "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/parser": "^7.24.7",
+ "@babel/types": "^7.24.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.24.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz",
+ "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.7",
+ "@babel/generator": "^7.24.8",
+ "@babel/helper-environment-visitor": "^7.24.7",
+ "@babel/helper-function-name": "^7.24.7",
+ "@babel/helper-hoist-variables": "^7.24.7",
+ "@babel/helper-split-export-declaration": "^7.24.7",
+ "@babel/parser": "^7.24.8",
+ "@babel/types": "^7.24.8",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.24.9",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz",
+ "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.24.8",
+ "@babel/helper-validator-identifier": "^7.24.7",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
+ "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jquery": {
+ "version": "3.5.30",
+ "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.30.tgz",
+ "integrity": "sha512-nbWKkkyb919DOUxjmRVk8vwtDb0/k8FKncmUKFi+NY+QXqWltooxTrswvz4LspQwxvLdvzBN1TImr6cw3aQx2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/sizzle": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.14.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
+ "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/sizzle": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
+ "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.32",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
+ "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/abab": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+ "deprecated": "Use your platform's native atob() and btoa() methods instead",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/acorn": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+ "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-globals": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.3",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz",
+ "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.23.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz",
+ "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001640",
+ "electron-to-chromium": "^1.4.820",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.1.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001642",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz",
+ "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz",
+ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssom": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
+ "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cssstyle": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+ "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssom": "~0.3.6"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cssstyle/node_modules/cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/data-urls": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
+ "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "abab": "^2.0.6",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/domexception": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+ "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.829",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.829.tgz",
+ "integrity": "sha512-5qp1N2POAfW0u1qGAxXEtz6P7bO1m6gpZr5hdf5ve6lxpLM7MpiM4jIPz7xcrNlClQMafbyUDDWjlIQZ1Mw0Rw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-encoding-sniffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+ "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
+ "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-junit": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz",
+ "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "strip-ansi": "^6.0.1",
+ "uuid": "^8.3.2",
+ "xml": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsdom": {
+ "version": "20.0.3",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
+ "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "abab": "^2.0.6",
+ "acorn": "^8.8.1",
+ "acorn-globals": "^7.0.0",
+ "cssom": "^0.5.0",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^3.0.2",
+ "decimal.js": "^10.4.2",
+ "domexception": "^4.0.0",
+ "escodegen": "^2.0.0",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^3.0.0",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.1",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.2",
+ "w3c-xmlserializer": "^4.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^2.0.0",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0",
+ "ws": "^8.11.0",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz",
+ "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.12",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz",
+ "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+ "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
+ "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.1.2",
+ "picocolors": "^1.0.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/w3c-xmlserializer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+ "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+ "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^3.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
old mode 100644
new mode 100755
index 4571e077..73e9fce4
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gmail-js",
- "version": "0.8.0",
+ "version": "1.1.16",
"description": "JavaScript API for Gmail (useful for chrome extensions)",
"main": "src/gmail.js",
"types": "src/gmail.d.ts",
@@ -9,9 +9,9 @@
"url": "https://github.com/KartikTalwar/gmail.js.git"
},
"scripts": {
- "lint": "./node_modules/.bin/eslint src/*.js",
- "tsc": "./node_modules/.bin/tsc",
- "test": "./node_modules/.bin/mocha test/test.*.js",
+ "lint": "eslint src/*.js",
+ "tsc": "tsc src/*.ts",
+ "test": "jest --watchAll=false --reporters=default --reporters=jest-junit",
"ci": "npm run tsc && npm run test && npm run lint"
},
"keywords": [
@@ -22,14 +22,13 @@
"gmail chrome extension",
"gmail firefox extension"
],
- "dependencies": {
- "jquery": "^3.3.1"
- },
"devDependencies": {
- "@types/jquery": "^1.10.27",
- "eslint": "^3.10.2",
- "mocha": "^3.1.2",
- "typescript": "^2.0.7"
+ "@types/jquery": "^3.5.14",
+ "eslint": "^8.23.1",
+ "jest": "^29.5.0",
+ "jest-junit": "^16.0.0",
+ "jsdom": "^20.0.0",
+ "typescript": "^4.8.3"
},
"author": "Kartik Talwar",
"license": "MIT",
diff --git a/src/gmail.d.ts b/src/gmail.d.ts
index 93d7039a..228fbd27 100644
--- a/src/gmail.d.ts
+++ b/src/gmail.d.ts
@@ -23,7 +23,8 @@ declare type StringDict = {
//
////////////////////////////////////////////////////////////////////////////////
-interface GmailTracker {
+interface GmailTracker {
+ dom_observers: { [observer in GmailDomObserver | T]?: DomObserverConfig };
globals: any[];
view_data: any[];
ik: string;
@@ -31,10 +32,10 @@ interface GmailTracker {
events: {}[];
actions: {}[];
watchdog: {
- before: {},
- on: {},
- after: {},
- dom: {}
+ before: { [action in GmailBindAction | T]?: Function[] };
+ on: { [action in GmailBindAction | T]?: Function[] };
+ after: { [action in GmailBindAction | T]?: Function[] };
+ dom: { [observer in GmailDomObserver | T]?: Function[] };
};
}
@@ -54,6 +55,12 @@ declare type GmailPageType =
*/
declare type GmailEmailAddress = string[];
+declare type GmailDomComposeRecipients = {
+ to: string[];
+ cc: string[];
+ bcc: string[];
+}
+
declare type GmailAttachmentDetails = {
attachment_id: string,
name: string,
@@ -188,7 +195,7 @@ interface GmailGet {
Returns a count of total unread emails for the current account.
You can also request the data individually using:
-
+
gmail.get.unread_inbox_emails()
gmail.get.unread_draft_emails()
gmail.get.unread_spam_emails()
@@ -244,7 +251,7 @@ interface GmailGet {
/**
Deprecated function. Migrate to `email_source_async` or `email_source_promise`!
*/
- email_source(email_id: string): string;
+ email_source(identifier: GmailEmailIdentifier): string;
/**
Retrieves raw MIME message source from the gmail server for the
specified email id. It takes the optional email_id parameter
@@ -255,12 +262,12 @@ interface GmailGet {
string or binary format depending on the value of the
`preferBinary`-parameter.
*/
- email_source_async(email_id: string, callback: (email_source: string | Uint8Array) => void, error_callback?: (jqxhr: JQueryXHR, textStatus: string, errorThrown: string) => void, preferBinary?: boolean): void;
+ email_source_async(identifier: GmailEmailIdentifier, callback: (email_source: string | Uint8Array) => void, error_callback?: (jqxhr: JQueryXHR, textStatus: string, errorThrown: string) => void, preferBinary?: boolean): void;
/**
Does the same as email_source_async, but uses ES6 promises.
*/
- email_source_promise(email_id: string): Promise;
- email_source_promise(email_id: string, preferBinary: boolean): Promise;
+ email_source_promise(identifier: GmailEmailIdentifier): Promise;
+ email_source_promise(identifier: GmailEmailIdentifier, preferBinary: boolean): Promise;
/**
Retrieves the a email/thread data from the server that is currently
visible. The data does not come from the DOM.
@@ -289,6 +296,10 @@ interface GmailCheck {
Returns True if the user is running Gmail with the new 2018 GUI
*/
is_new_gui(): boolean;
+ /**
+ Returns True if the compose UI uses new UI as announced [here](https://workspaceupdates.googleblog.com/2021/10/visual-updates-for-composing-email-in-gmail.html)
+ */
+ is_peoplekit_compose(composeElement: JQuery | HTMLElement): boolean;
/**
Returns True if the conversation is threaded False otherwise
*/
@@ -382,6 +393,12 @@ interface GmailCheck {
otherwise (i.e. displayed individually)
*/
is_conversation_view(): boolean;
+
+ data: {
+ is_email_id(email_id: string): boolean;
+ is_thread_id(email_id: string): boolean;
+ is_legacy_email_id(email_id: string): boolean;
+ }
}
@@ -404,7 +421,7 @@ interface GmailDomThread {
/**
Retrieve preconfigured dom elements for this email
*/
- dom(lookup: GmailDomThreadLookup): JQuery,
+ dom(lookup?: GmailDomThreadLookup): JQuery,
}
interface GmailDomAttachment {
@@ -441,7 +458,7 @@ interface GmailDomEmail {
Optionally receives an array of these objects if multiple recipients
Returns an array of objects containing email & name of who is showing in the DOM as the email is to
*/
- to(to_array: GmailDomEmailEntry | GmailDomEmailEntry[]): GmailDomEmailEntry[];
+ to(to_array?: GmailDomEmailEntry | GmailDomEmailEntry[]): GmailDomEmailEntry[];
/**
Retries the DOM elements which represents the emails attachments
Returns undefined if UI-elements are not yet ready for parsing.
@@ -462,7 +479,7 @@ interface GmailDomEmail {
/**
Retrieve preconfigured dom elements for this email
*/
- dom(lookup: GmailDomEmailLookup): JQuery;
+ dom(lookup?: GmailDomEmailLookup): JQuery;
/**
An object for interacting with an email currently present in the DOM. Represents a conversation thread
Provides a number of methods and properties to access & interact with it
@@ -473,9 +490,20 @@ interface GmailDomEmail {
declare type GmailDomComposeLookup =
'to' | 'cc' | 'bcc' | 'id' | 'draft' | 'subject' | 'subjectbox'
- | 'all_subjects' | 'body' | 'reply' | 'forward' | 'from' | 'send_button';
+ | 'all_subjects' | 'body' | 'quoted_reply' | 'reply' | 'forward' | 'from' | 'send_button' | 'show_cc' | 'show_bcc';
+
+interface GmailMessageRow {
+ summary: string;
+ from: {
+ name: string,
+ email: string,
+ };
+ $el: JQuery;
+ thread_id: string;
+ legacy_email_id: string | undefined;
+}
-declare type GmailDomCompose = {
+interface GmailDomCompose {
$el: JQuery,
/**
Retrieve the compose id
@@ -485,29 +513,41 @@ declare type GmailDomCompose = {
Retrieve the draft email id
*/
email_id(): string,
+ /**
+ Retrieve the draft email id
+ */
+ thread_id(): string
/**
Is this compose instance inline (as with reply & forwards) or a popup (as with a new compose)
*/
is_inline(): boolean,
+ /**
+ Compose type - reply / forward / compose (new)
+ */
+ type(): GmailComposeType,
/**
Retrieves to, cc, bcc and returns them in a hash of arrays
Parameters:
options.type string to, cc, or bcc to check a specific one
options.flat boolean if true will just return an array of all recipients instead of splitting out into to, cc, and bcc
*/
- recipients(options?: { type: string, flat: boolean }): GmailEmailAddress[];
+ recipients(options?: { type: 'to' | 'cc' | 'bcc' }): GmailDomComposeRecipients;
+ recipients(options?: { flat: boolean }): string[];
/**
- Retrieve the current 'to' recipients
+ Retrieve the typing area for "to" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
- to(): string;
+ to(to?: string): JQuery;
/**
- Retrieve the current 'cc' recipients
+ Retrieve the typing area for "cc" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
- cc(): string;
+ cc(cc?: string): JQuery;
/**
- Retrieve the current 'bcc' recipients
+ Retrieve the typing area for "bcc" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
- bcc(): string;
+ bcc(bcc?: string): JQuery;
/**
Get/Set the current subject
Parameters:
@@ -523,18 +563,26 @@ declare type GmailDomCompose = {
Get/Set the email html body
*/
body(body?: string): string;
- /*
- Triggers the same action as clicking the "send" button would do.
+ /**
+ Get the email attachments
+ */
+ attachments(): GmailDomAttachment[];
+ /**
+ Triggers the same action as clicking the "send" button would do.
*/
send(): void;
/**
Map find through to jquery element
*/
find(selector: string): JQuery;
+ /**
+ Close compose window
+ */
+ close(): void;
/**
Retrieve preconfigured dom elements for this compose window
*/
- dom(lookup: GmailDomComposeLookup): JQuery;
+ dom(lookup?: GmailDomComposeLookup): JQuery;
}
interface GmailDom {
@@ -574,6 +622,10 @@ interface GmailDom {
* Gets a jQuery object representing the Search input from main header.
*/
search_bar(): JQuery;
+ /**
+ * Get's all the visible email threads in the current folder.
+ */
+ visible_messages(): GmailMessageRow[];
/**
* Returns all known compose DOM elements.
*/
@@ -620,7 +672,7 @@ interface GmailTools {
observes every element inserted into the DOM by Gmail and looks at the classes on those elements,
checking for any configured observers related to those classes
*/
- insertion_observer(target: HTMLElement | string, dom_observers: any, dom_observer_map: any, sub: any): void;
+ insertion_observer(target: HTMLElement | string, dom_observers: { [observer: string]: DomObserverConfig }, dom_observer_map: { [className: string]: string[] }, sub?: string): void;
make_request(link: string, method: GmailHttpRequestMethod, disable_cache: boolean): string;
make_request_async(link: string, method: GmailHttpRequestMethod, callback: (data: string) => void, disable_cache: boolean): void;
@@ -664,8 +716,15 @@ interface GmailTools {
extract_name(str: string): string;
i18n(label: string): string;
add_toolbar_button(content_html: string, onClickFunction: Function, styleClass: string): JQuery;
- add_right_toolbar_button(content_html: string, onClickFunction: Function, styleClass: string): JQuery;
- add_compose_button(composeWindow: GmailDomCompose, content_html: string, onClickFunction: Function, styleClass: string): JQuery;
+ add_right_toolbar_button(content_html: string, onClickFunction: Function, styleClass: string): JQuery;
+ add_compose_button(composeWindow: GmailDomCompose, content_html: string, onClickFunction: Function, styleClass?: string): JQuery;
+ add_more_send_option(
+ composeWindow: GmailDomCompose,
+ buttonText: string,
+ onClickFunction: Function,
+ styleClass?: string | undefined,
+ imgClass?: string | undefined
+ ): JQuery;
/**
adds a button to an email attachment.
@@ -679,7 +738,7 @@ interface GmailTools {
add_attachment_button(attachment: GmailDomAttachment, contentHtml: string | null, customCssClas: string | null, tooltip: string, onClickFunction: Function): JQuery;
remove_modal_window(): void;
- add_modal_window(title: string, content_html: string, onClickOk: Function, onClickCancel?: Function, onClickClose?: Function): void;
+ add_modal_window(title: string, content_html: string, onClickOk: Function, onClickCancel?: Function, onClickClose?: Function, okText?: string, cancelText?: string): void;
/**
* Show/Hide compose window
*/
@@ -701,13 +760,30 @@ declare type GmailBindAction =
| 'label' | 'archive' | 'move_to_inbox' | 'delete_forver' | 'delete_message_in_thread'
| 'restore_message_in_thread' | 'star' | 'unstar' | 'mark_as_important' | "load"
| 'mark_as_not_important' | 'filter_messages_like_these' | 'mute' | 'unmute'
- | 'add_to_tasks' | 'move_label' | 'save_draft' | 'discard_draft' | 'send_message'
+ | 'add_to_tasks' | 'move_label' | 'save_draft' | 'discard_draft' | 'send_message' | 'send_scheduled_message'
| 'expand_categories' | 'delete_label' | 'show_newly_arrived_message' | 'poll'
| 'new_email' | 'refresh' | 'open_email' | 'upload_attachment' | 'compose'
| 'compose_cancelled' | 'recipient_change' | 'view_thread' | 'view_email'
| 'load_email_menu';
+declare type GmailDomObserver =
+ 'view_thread' | 'view_email' | 'load_email_menu' | 'recipient_change' | 'compose'
+
+interface HttpEventRequestParams {
+ url: object,
+ url_raw: string;
+ body: string;
+ body_params: object;
+ method: string;
+}
-interface GmailObserve {
+interface DomObserverConfig {
+ class: string | string[];
+ selector?: string;
+ sub_selector?: string;
+ handler?: Function;
+}
+
+interface GmailObserve {
/**
After an observer has been bound through gmail.observe.bind() (via a
call to events gmail.observe.before(), gmail.observe.on(), or
@@ -725,7 +801,7 @@ interface GmailObserve {
/**
Bind a specified callback to an array of callbacks against a specified type & action
*/
- bind(type: GmailBindType, action: Function, callback: Function): void;
+ bind(type: GmailBindType, action: GmailBindAction | T, callback: Function): void;
/**
an on event is observed just after gmail sends an xhr request
@@ -735,6 +811,7 @@ interface GmailObserve {
on(action: "load_email_menu", callback: (obj: JQuery) => void): void;
on(action: "compose", callback: (obj: GmailDomCompose, type: GmailComposeType) => void): void;
on(action: "load", callback: () => void): void;
+ on(action: "http_event", callback: (request: HttpEventRequestParams, xhr: XMLHttpRequest) => void): void;
/**
This is the key feature of gmail.js. This method allows you to
add triggers to all of these actions so you can build your
@@ -747,39 +824,40 @@ interface GmailObserve {
Your callback will be fired directly after Gmail's XMLHttpRequest
has been sent off the the Gmail servers.
*/
- on(action: GmailBindAction, callback: Function, response_callback?: Function): void;
+ on(action: GmailBindAction | T, callback: Function, response_callback?: Function): void;
/**
an before event is observed just prior to the gmail xhr request being sent
before events have the ability to modify the xhr request before it is sent
*/
- before(action: GmailBindAction, callback: Function): void;
+ before(action: GmailBindAction | T, callback: Function): void;
/**
an after event is observed when the gmail xhr request returns from the server
with the server response
*/
- after(action: "send_message", callback: (url: string, body: string, data: any, xhr: XMLHttpRequest) => void): void;
- after(action: GmailBindAction, callback: Function): void;
+ after(action: "send_message", callback: (url: string, body: string, data: any, response: any, xhr: XMLHttpRequest) => void): void;
+ after(action: "http_event", callback: (request: HttpEventRequestParams, responseData: any, xhr: XMLHttpRequest) => void): void;
+ after(action: GmailBindAction | T, callback: Function): void;
/**
Checks if a specified action & type has anything bound to it
If type is null, will check for this action bound on any type
If action is null, will check for any actions bound to a type
*/
- bound(action: GmailBindAction, type: GmailBindType): boolean;
+ bound(action: GmailBindAction | T, type: GmailBindType): boolean;
/**
Clear all callbacks for a specific type (before, on, after, dom) and action
If action is null, all actions will be cleared
If type is null, all types will be cleared
*/
- off(action: GmailBindAction, type: GmailBindType): void;
+ off(action: GmailBindAction | T, type: GmailBindType): void;
/**
Trigger any specified events bound to the passed type
Returns true or false depending if any events were fired
*/
- trigger(type: GmailBindType, events: any, xhr: XMLHttpRequest): boolean;
+ trigger(type: GmailBindType, events: { [action in GmailBindAction | T]?: any[] }, xhr: XMLHttpRequest): boolean;
/**
Trigger any specified DOM events passing a specified element & optional handler
*/
- trigger_dom(observer: any, element: HTMLElement, handler?: Function): void;
+ trigger_dom(observer: GmailDomObserver | T, element: HTMLElement, handler?: Function): void;
initialize_dom_observers(): void;
@@ -792,13 +870,13 @@ interface GmailObserve {
className / args - for a simple observer, this arg can simply be the class on an inserted DOM element that identifies this event should be
triggered. For a more complicated observer, this can be an object containing properties for each of the supported DOM observer config arguments
*/
- register(action: string, args: string | StringDict): void;
+ register(action: T, args: string | DomObserverConfig): void;
/**
Observe DOM nodes being inserted. When a node with a class defined in api.tracker.dom_observers is inserted,
trigger the related event and fire off any relevant bound callbacks
This function should return true if a dom observer is found for the specified action
*/
- on_dom(action: GmailBindAction, callback: Function): void;
+ on_dom(action: GmailBindAction | T, callback: Function): boolean;
}
@@ -808,11 +886,15 @@ interface GmailObserve {
//
////////////////////////////////////////////////////////////////////////////////
+type GmailEmailIdentifier = string | GmailNewEmailData | GmailDomEmail | HTMLElement;
+type GmailThreadIdentifier = string | GmailNewEmailData | GmailDomEmail | GmailDomThread;
+
interface GmailHelper {
/**
* Dispatch mousedown and mouseup event on passed element
*/
trigger_mouse_click(element: HTMLElement): boolean;
+ clean_thread_id(thread_id: string): string;
get: {
is_delegated_inbox(): boolean;
@@ -821,6 +903,9 @@ interface GmailHelper {
email_data_pre(email_id?: string): string;
email_data_post(get_data: string): GmailEmailData;
email_source_pre(email_id?: string): string;
+ email_legacy_id(identifier: GmailEmailIdentifier): string | null;
+ email_new_id(identifier: GmailEmailIdentifier): string | null;
+ thread_id(identifier: GmailThreadIdentifier): string | null;
}
}
@@ -865,28 +950,39 @@ interface GmailNewEmailAddress {
address: string;
}
-interface GmailNewEmailAttachment {
+interface GmailNewEmailData {
id: string;
- name: string;
- contentType: string;
- url: string;
- size: Number;
+ legacy_email_id: string;
+ thread_id: string;
+ smtp_id: string;
+ is_draft: boolean,
+ subject: string;
+ timestamp: number;
+ date: Date;
+ from: GmailNewEmailAddress;
+ to: GmailNewEmailAddress[];
+ cc: GmailNewEmailAddress[];
+ bcc: GmailNewEmailAddress[];
+ attachments: GmailAttachmentDetails[];
+ content_html: string;
+ $email_node?: any;
+ $thread_node?: any;
}
-interface GmailNewEmailData {
- thread_id: string;
- email_id: string;
- legacy_email_id: string;
- email_smtp_id: string;
- email_subject: string;
- email_timestamp: Number;
- email_date: Date;
- email_sender_address: string;
- email_to: GmailNewEmailAddress[];
- email_cc: GmailNewEmailAddress[];
- email_bcc: GmailNewEmailAddress[];
- email_attachments: GmailNewEmailAttachment[];
- $data_node: object
+interface GmailSentEmailData {
+ 1: string;
+ id: string;
+ subject: string;
+ timestamp: number;
+ date: Date;
+ from: GmailNewEmailAddress;
+ to: GmailNewEmailAddress[];
+ cc: GmailNewEmailAddress[];
+ bcc: GmailNewEmailAddress[];
+ attachments: GmailAttachmentDetails[];
+ content_html: string;
+ ishtml: boolean;
+ $email_node?: any;
}
interface GmailNewThreadData {
@@ -896,9 +992,12 @@ interface GmailNewThreadData {
interface GmailNewGet {
/**
- * Returns the new-style email_id of the latest email visible in the DOM.
+ * Returns the new-style email_id of the latest email visible in the DOM,
+ * or for the provided email-node if provided.
+ *
+ * @param emailElem: Node to extract email-id from or DomEmail. Optional.
*/
- email_id(): string;
+ email_id(emailElem?: HTMLElement | GmailDomEmail): string;
/**
* Returns the new-style thread_id of the current thread visible in the DOM.
*/
@@ -908,34 +1007,41 @@ interface GmailNewGet {
*
* @param email_id: new style email id. Legacy IDs not supported. If empty, default to latest in view.
*/
- email_data(email_id?: string): GmailNewEmailData;
+ email_data(identifier?: GmailEmailIdentifier): GmailNewEmailData | null;
/**
* Returns available information about a specific thread.
*
* @param thread_id: new style thread id. Legacy IDs not supported. If empty, default to current.
*/
- thread_data(thread_id?: string): GmailNewThreadData;
+ thread_data(identifier?: GmailThreadIdentifier): GmailNewThreadData | null;
}
interface GmailNew {
get: GmailNewGet;
}
+interface GmailCache {
+ debug_xhr_fetch: boolean;
+ emailIdCache: { (emailId: string): GmailNewEmailData };
+ emailLegacyIdCache: { (legacyEmailId: string): GmailNewEmailData };
+ threadCache: { (threadId: string): GmailNewThreadData };
+}
+
////////////////////////////////////////////////////////////////////////////////
//
// actual gmail-class
//
////////////////////////////////////////////////////////////////////////////////
-declare class Gmail {
- constructor(localJQuery?: JQueryStatic);
+declare class Gmail {
+ constructor(localJQuery: JQueryStatic | false);
version: string;
/**
These are some of the variables that are tracked and kept in
memory while the rest of the methods are in use.
*/
- tracker: GmailTracker;
+ tracker: GmailTracker;
get: GmailGet;
check: GmailCheck;
/**
@@ -947,7 +1053,7 @@ declare class Gmail {
use. See source for input params
*/
tools: GmailTools;
- observe: GmailObserve;
+ observe: GmailObserve;
helper: GmailHelper;
chat: GmailChat;
compose: GmailCompose;
@@ -957,4 +1063,6 @@ declare class Gmail {
old: {
get: GmailGet;
};
+
+ cache: GmailCache;
}
diff --git a/src/gmail.js b/src/gmail.js
old mode 100755
new mode 100644
index 67f7cb28..b9a8e249
--- a/src/gmail.js
+++ b/src/gmail.js
@@ -13,20 +13,32 @@ var Gmail = function(localJQuery) {
other extensions that use $ for other purposes.
*/
var $;
- if (typeof localJQuery !== "undefined") {
+ if (localJQuery === false) {
+ // leave $ undefined, which may be fine for some purposes.
+ } else if (typeof localJQuery !== "undefined") {
$ = localJQuery;
} else if (typeof jQuery !== "undefined") {
$ = jQuery;
} else {
- // try load jQuery through node.
+ throw new Error("GmailJS requires jQuery to be present in global scope or provided as a constructor argument.");
+ }
+
+ var window_opener = typeof (window) !== "undefined" ? window.opener : null;
+ if (window_opener) {
try {
- $ = require("jquery");
- }
- catch(err) {
- // else leave $ undefined, which may be fine for some purposes.
+ // access to window.opener domain will fail in case of cross-origin access
+ var opener_domain = window_opener.document.domain;
+ if (opener_domain !== window.document.domain) {
+ console.warn("GmailJS: window.opener domain differs from window domain.");
+ window_opener = null;
+ }
+ } catch (error) {
+ console.warn("GmailJS: Unable to access window.opener!", error);
+ window_opener = null;
}
}
+ /** @type Gmail */
var api = {
get : {},
observe : {},
@@ -39,26 +51,34 @@ var Gmail = function(localJQuery) {
helper : {get: {}}
};
+ api.DISABLE_OLD_GMAIL_API_DEPRECATION_WARNINGS = false;
+
+ function oldGmailApiDeprecated(text = "Migrate to new API compatible with new Gmail to silence this warning!") {
+ if (api.DISABLE_OLD_GMAIL_API_DEPRECATION_WARNINGS) {
+ return;
+ }
+
+ console.warn("GmailJS: using deprecated API for old Gmail.", text);
+ }
+
api.version = "0.8.0";
api.tracker.globals = typeof GLOBALS !== "undefined"
? GLOBALS
: (
- typeof(window) !== "undefined" && window.opener !== null && typeof window.opener.GLOBALS !== "undefined"
- ? window.opener.GLOBALS
- : []
+ window_opener && window_opener.GLOBALS || []
);
api.tracker.view_data = typeof VIEW_DATA !== "undefined"
? VIEW_DATA
: (
- typeof(window) !== "undefined" && window.opener !== null && typeof window.opener.VIEW_DATA !== "undefined"
- ? window.opener.VIEW_DATA
- : []
+ window_opener && window_opener.VIEW_DATA || []
);
api.tracker.ik = api.tracker.globals[9] || "";
+ api.tracker.mla = undefined;
api.tracker.hangouts = undefined;
// cache-store for passively pre-fetched/intercepted email-data from load_email_data.
api.cache = {};
+ api.cache.debug_xhr_fetch = false;
api.cache.emailIdCache = {};
api.cache.emailLegacyIdCache = {};
api.cache.threadCache = {};
@@ -74,35 +94,41 @@ var Gmail = function(localJQuery) {
};
+ /**
+ * Gets list of logged in accounts.
+ *
+ * @returns {GmailLoggedInAccount[]}
+ */
api.get.loggedin_accounts = function() {
- var i, j, data;
- var users = [];
-
- var globals17 = api.tracker.globals[17];
- for (i in globals17) {
- // at least for the delegated inboxes, the index of the mla is not stable
- // it was observed to be somewhere between 22 and 24, but we should not depend on it
- data = globals17[i];
-
- if (data[0] === "mla") {
- for(j in data[1]) {
- users.push({
- name : data[1][j][4],
- email : data[1][j][0],
- index: data[1][j][3]
- });
- }
+ const data = api.tracker.mla;
- return users;
- }
+ if (!Array.isArray(data)) {
+ return [];
}
- return users;
+ return data[1].map(item => ({
+ name: item[4],
+ email: item[0],
+ index: item[3]
+ }));
};
api.get.user_email = function() {
- return api.tracker.globals[10];
+ let user_email = api.tracker.globals[10];
+ if (user_email) {
+ return user_email;
+ }
+
+ const elements = document.getElementsByClassName("eYSAde");
+ for (const el of elements) {
+ if (el.innerHTML.indexOf("@") === -1) {
+ return el.innerHTML;
+ }
+ }
+
+ // give up
+ return null;
};
@@ -115,28 +141,25 @@ var Gmail = function(localJQuery) {
};
+ /**
+ * Gets email of current logged-in user, who views delegated account inbox.
+ *
+ * @returns {string|null} Returns null when Gmail is opened for a non-delegated account or when there is no
+ * information about current logged-in user.
+ */
api.get.delegated_to_email = function() {
if (!api.helper.get.is_delegated_inbox()) {
return null;
}
- var i, account;
- var userIndexPrefix = "/u/";
- var pathname = window.location.pathname;
- var delegatedToUserIndex = parseInt(pathname.substring(pathname.indexOf(userIndexPrefix) + userIndexPrefix.length), 10);
+ const userIndexPrefix = "/u/";
+ const pathname = window.location.pathname;
+ const delegatedToUserIndex = parseInt(pathname.substring(pathname.indexOf(userIndexPrefix) + userIndexPrefix.length), 10);
- var loggedInAccounts = api.get.loggedin_accounts();
- if (loggedInAccounts && loggedInAccounts.length > 0) {
- for (i in loggedInAccounts) {
- account = loggedInAccounts[i];
- if (account.index === delegatedToUserIndex) {
- return account.email;
- }
- }
- }
+ const loggedInAccounts = api.get.loggedin_accounts();
+ const loggedInAccount = loggedInAccounts.find(account => account.index === delegatedToUserIndex);
- // as a last resort, we query the DOM of the upper right account selection menu
- return $(".gb_rb[href$='" + userIndexPrefix + delegatedToUserIndex + "'] .gb_yb").text().split(" ")[0];
+ return loggedInAccount ? loggedInAccount.email : null;
};
api.helper.get.is_locale = function(locale) {
@@ -246,6 +269,15 @@ var Gmail = function(localJQuery) {
}
}
+ // and in even newer gmail this seems to work:
+ if (globals[4]) {
+ let locale = globals[4].split(".")[1];
+ locale = api.helper.filter_locale(locale);
+ if (locale) {
+ return locale;
+ }
+ }
+
return null;
};
@@ -258,12 +290,27 @@ var Gmail = function(localJQuery) {
};
api.check.is_thread = function() {
- var check_1 = $(".nH .if").children(":eq(1)").children().children(":eq(1)").children();
+ // There are currently two selectors in use for view_thread: Bu and nH,
+ // Which correspond to two different ways a thread may be viewed by the user.
+ // There are two different code paths to determine if we are within a thread.
+
+ // This is the nH path:
+ // this should match the sub_selector (nH -> if/iY):
+ var check_1 = $(".nH .if,.iY").children(":eq(1)").children().children(":eq(1)").children();
+
+ // And this is the Bu path. We don't bother here checking for the sub_selector.
var check_2 = api.get.email_ids();
return check_1.length > 1 || check_2.length > 1;
};
+ /**
+ * New contact selection UI as announced in
+ * https://workspaceupdates.googleblog.com/2021/10/visual-updates-for-composing-email-in-gmail.html
+ **/
+ api.check.is_peoplekit_compose = function (el) {
+ return $(el).find("div[name=to] input[peoplekit-id]").length !== 0;
+ };
api.dom.inbox_content = function() {
return $("div[role=main]:first");
@@ -304,12 +351,12 @@ var Gmail = function(localJQuery) {
api.check.is_tabbed_inbox = function() {
- return $(".aKh").length === 1;
+ return document.querySelectorAll(".aKh").length === 1;
};
api.check.is_right_side_chat = function() {
- var chat = $(".ApVoH");
+ var chat = document.querySelectorAll(".ApVoH");
if(chat.length === 0) {
return false;
}
@@ -336,11 +383,10 @@ var Gmail = function(localJQuery) {
api.get.storage_info = function() {
- var div = $(".md.mj").find("div")[0];
- var used = $(div).find("span")[0].text;
- var total = $(div).find("span")[1].text;
+ var div = document.querySelector(".md.mj div");
+ var used = div.querySelectorAll("span")[0].textContent.replace(/,/g, '.'); //convert to standard decimal
+ var total = div.querySelectorAll("span")[1].textContent.replace(/,/g, '.');
var percent = parseFloat(used.replace(/[^0-9\.]/g, "")) * 100 / parseFloat(total.replace(/[^0-9\.]/g, ""));
-
return {used : used, total : total, percent : Math.floor(percent)};
};
@@ -385,13 +431,7 @@ var Gmail = function(localJQuery) {
};
api.dom.right_toolbar = function() {
- var rtb = $("[gh='tm'] [gh='s']").parent();
-
- while($(rtb).children().length === 1){
- rtb = $(rtb).children().first();
- }
-
- return rtb;
+ return $("[gh='tm'] .Cr.aqJ");
};
api.check.is_inside_email = function() {
@@ -399,7 +439,7 @@ var Gmail = function(localJQuery) {
return false;
}
- var items = $(".ii.gt .a3s.aXjCH");
+ var items = document.querySelectorAll(".ii.gt .a3s");
var ids = [];
for(var i=0; i 0;
+ return document.querySelector(".qh") !== null;
};
api.check.is_rapportive_installed = function() {
- return $("#rapportive-sidebar").length === 1;
+ return document.querySelector("#rapportive-sidebar") !== null;
};
api.check.is_streak_installed = function() {
- return $("[id^='bentoBox'],[id*=' bentoBox'],[class*=' bentoBox'],[class*='bentoBox']").length > 0;
+ return document.querySelector("[id^='bentoBox'],[id*=' bentoBox'],[class*=' bentoBox'],[class*='bentoBox']") !== null;
};
api.check.is_anydo_installed = function() {
- return $("[id^='anydo'],[id*=' anydo'],[class*=' anydo'],[class*='anydo']").length > 0;
+ return document.querySelector("[id^='anydo'],[id*=' anydo'],[class*=' anydo'],[class*='anydo']") !== null;
};
api.check.is_boomerang_installed = function() {
- return $("[id^='b4g_'],[id*=' b4g_'],[class*=' b4g_'],[class*='b4g_']").length > 0;
+ return document.querySelector("[id^='b4g_'],[id*=' b4g_'],[class*=' b4g_'],[class*='b4g_']") !== null;
};
api.check.is_xobni_installed = function() {
- return $("#xobni_frame").length > 0;
+ return document.querySelector("#xobni_frame") !== null;
};
api.check.is_signal_installed = function() {
- return $("[id^='Signal'],[id*=' Signal'],[class*=' signal'],[class*='signal']").length > 0;
+ return document.querySelector("[id^='Signal'],[id*=' Signal'],[class*=' signal'],[class*='signal']") !== null;
};
@@ -566,89 +611,50 @@ var Gmail = function(localJQuery) {
api.get.unread_inbox_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("inbox") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.split(":")[0].replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("inbox");
};
api.get.unread_draft_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("drafts") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("drafts");
};
api.get.unread_spam_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("spam") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("spam");
};
api.get.unread_forum_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("forums") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("forums");
};
api.get.unread_update_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("updates") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("updates");
};
api.get.unread_promotion_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("promotions") + "']");
-
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
- }
- }
-
- return 0;
+ return api.helper.get.navigation_count("promotions");
};
api.get.unread_social_emails = function() {
- var dom = $("div[role=navigation]").find("[title*='" + api.tools.i18n("social_updates") + "']");
+ return api.helper.get.navigation_count("social_updates");
+ };
+
+ api.helper.get.navigation_count = function(i18nName) {
+ const title = api.tools.i18n(i18nName);
+ const dom = document.querySelectorAll("div[role=navigation] [title*='" + title + "']");
- if(dom.length > 0) {
- if(dom[0].title.indexOf("(") !== -1) {
- return parseInt(dom[0].title.replace(/[^0-9]/g, ""));
+ if (dom.length > 0) {
+ // this check should implicitly always be true, but better safe than sorry?
+ if(dom[0].title.indexOf(title) !== -1) {
+ const value = parseInt(dom[0].attributes['aria-label'].value.replace(/[^0-9]/g, ""));
+ if (!isNaN(value)) {
+ return value;
+ }
}
}
@@ -658,7 +664,7 @@ var Gmail = function(localJQuery) {
api.get.beta = function() {
var features = {
- "new_nav_bar" : $("#gbz").length === 0
+ "new_nav_bar" : document.querySelector("#gbz") !== null
};
return features;
@@ -678,12 +684,8 @@ var Gmail = function(localJQuery) {
};
- api.tools.error = function(str) {
- if (console) {
- console.error(str);
- } else {
- throw(str);
- }
+ api.tools.error = function(str, ...args) {
+ console.error(str, ...args);
};
api.tools.parse_url = function(url) {
@@ -961,9 +963,7 @@ var Gmail = function(localJQuery) {
triggered[action_map[action]] = response;
}
- if(params.method === "POST" && (typeof params.url.SID === "string"
- || typeof params.url.ik === "string"
- || typeof params.url.act === "string")) {
+ if(params.method === "POST") {
triggered.http_event = [params]; // send every event and all data
}
@@ -984,8 +984,8 @@ var Gmail = function(localJQuery) {
api.check.data.is_thread = function(obj) {
return obj
&& typeof obj === "object"
- && obj["1"]
- && api.check.data.is_thread_id(obj["1"]);
+ && obj["0"]
+ && api.check.data.is_thread_id(obj["0"]);
};
api.check.data.is_email_id = function(id) {
@@ -998,8 +998,21 @@ var Gmail = function(localJQuery) {
api.check.data.is_email = function(obj) {
return obj
&& typeof obj === "object"
- && obj["1"]
- && api.check.data.is_email_id(obj["1"]);
+ && obj["0"]
+ && api.check.data.is_email_id(obj["0"]);
+ };
+
+ /** New payload, see https://github.com/KartikTalwar/gmail.js/issues/722 */
+ api.check.data.is_email_new = function(obj) {
+ return obj
+ && obj[0]
+ && api.check.data.is_email_id(obj[0]);
+ };
+
+ api.check.data.is_legacy_email_id = function(id) {
+ return id
+ && typeof id === "string"
+ && /^[0-9a-f]{16,}$/.test(id);
};
api.check.data.is_action = function(obj) {
@@ -1137,6 +1150,7 @@ var Gmail = function(localJQuery) {
};
api.tools.check_event_type = function(threadObj) {
+ const apply_label = "^x_";
const action_map = {
// "" : "add_to_tasks",
"^a": "archive",
@@ -1147,7 +1161,7 @@ var Gmail = function(localJQuery) {
// "" : "discard_draft",
// "" : "expand_categories",
// "" : "filter_messages_like_these",
- // "" : "label",
+ "^x_" : "label",
// "^io_im^imi": "mark_as_important",
// "^imn": "mark_as_not_important",
// "" : "mark_as_not_spam",
@@ -1176,13 +1190,19 @@ var Gmail = function(localJQuery) {
if (threadData && api.check.data.is_action(threadData)) {
const action = api.tools.get_action(threadData);
- return action_map[action];
+ //Check if label is applied to email / existing email is moved to an label
+ if(action.startsWith(apply_label) && api.check.data.is_first_type_action(threadData)) {
+ return action_map[apply_label];
+ } else {
+ return action_map[action];
+ }
+
} else {
return null;
}
};
- api.tools.parse_fd_email = function(json) {
+ api.tools.parse_fd_bv_contacts = function(json) {
if (!json || !Array.isArray(json)) {
return [];
}
@@ -1190,28 +1210,67 @@ var Gmail = function(localJQuery) {
const res = [];
for (let item of json) {
- res.push({
- name: item[3],
- address: item[2]
- });
+ res.push(api.tools.parse_fd_bv_contact(item));
}
return res;
};
+ api.tools.parse_fd_bv_is_draft = function(item) {
+ try {
+ if (!Array.isArray(item)) return false; // warning: case not seen during testing and value is untrustworthy
+ return item.includes('^r') && item.includes('^r_bt');
+ }
+ catch (e) {
+ return false; // warning: case not seen during testing and value is untrustworthy
+ }
+
+ };
+
+ api.tools.parse_fd_bv_contact = function(item) {
+ try
+ {
+ return {
+ name: item["2"],
+ address: item["1"]
+ };
+ }
+ catch (e) {
+ return null;
+ }
+ };
+
api.tools.parse_fd_attachments = function(json) {
let res = [];
if (Array.isArray(json)) {
for (let item of json) {
- let data = item["1"]["4"] || "";
+ let data = item["0"]["3"] || "";
+
+ res.push({
+ attachment_id: item["0"]["1"],
+ name: data["2"],
+ type: data["3"],
+ url: api.tools.check_fd_attachment_url(http://github.com/data[%221%22]),
+ size: Number.parseInt(data["4"])
+ });
+ }
+ }
+
+ return res;
+ };
+ api.tools.parse_fd_embedded_json_attachments = function(json) {
+ let res = [];
+
+ if (Array.isArray(json)) {
+ for (let item of json) {
res.push({
- id: item["1"]["2"],
- name: data["3"],
- contentType: data["4"],
- url: data["2"],
- size: Number.parseInt(data["5"])
+ attachment_id: item[3],
+ name: item[1],
+ type: item[0],
+ url: api.tools.check_fd_attachment_url(http://github.com/item[5]),
+ size: item[2]
});
}
}
@@ -1219,9 +1278,70 @@ var Gmail = function(localJQuery) {
return res;
};
+ api.tools.check_fd_attachment_url = function(url) {
+ var userAccountUrlPart = api.tracker.globals[7];
+ if (url && userAccountUrlPart && url.indexOf(userAccountUrlPart) < 0) {
+ url = url.replace('/mail/?', userAccountUrlPart + '?');
+ }
+
+ return url;
+ };
+
+ api.tools.parse_fd_request_html_payload = function(fd_email) {
+ let fd_email_content_html = null;
+ try {
+ const fd_html_containers = fd_email["1"]["5"]["1"];
+
+ for (let fd_html_container of fd_html_containers) {
+ fd_email_content_html = (fd_email_content_html || "") + fd_html_container["2"]["1"];
+ }
+ }
+ catch(e) {
+ // don't crash gmail when we cant parse email-contents
+ }
+
+ return fd_email_content_html;
+ };
+
+ api.tools.parse_fd_embedded_json_content_html = function (fd_email) {
+ let fd_email_content_html = null;
+ try {
+ const fd_html_containers = fd_email["8"]["1"];
+
+ for (let fd_html_container of fd_html_containers) {
+ fd_email_content_html = (fd_email_content_html || "") + fd_html_container["2"]["1"];
+ }
+ } catch (e) {
+ // don't crash gmail when we cant parse email-contents
+ }
+
+ return fd_email_content_html;
+ };
+
+ api.tools.parse_fd_request_payload_get_email2 = function(fd_thread_container, fd_email_id) {
+ try {
+ const fd_emails2 = fd_thread_container["1"]["1"];
+ const fd_email2 = fd_emails2.filter(i => i["0"] === fd_email_id);
+ return fd_email2[0];
+ }
+ catch (e) {
+ return {};
+ }
+ };
+
+ api.tools.parse_fd_embedded_json_get_email = function (fd_thread_container, fd_email_id) {
+ try {
+ const fd_emails2 = fd_thread_container["1"]["4"];
+ const fd_email2 = fd_emails2.filter(i => i["0"] === fd_email_id);
+ return fd_email2[0];
+ } catch (e) {
+ return {};
+ }
+ };
+
api.tools.parse_fd_request_payload = function(json) {
// ensure JSON-format is known and understood?
- let thread_root = json["2"];
+ let thread_root = json["1"];
if (!thread_root || !Array.isArray(thread_root)) {
return null;
}
@@ -1232,55 +1352,486 @@ var Gmail = function(localJQuery) {
const fd_threads = thread_root; // array
for (let fd_thread_container of fd_threads) {
- const fd_thread_id = fd_thread_container["1"];
+ const fd_thread_id = fd_thread_container["0"];
- // lots of thread and email-info ... sometimes! in fd_thread_container["2"]
- // but if we 1. don't need it, and 2. can't guarantee it,
- // don't put in any effort to create false expectations for library users.
-
- let fd_emails = fd_thread_container["3"]; // array
+ let fd_emails = fd_thread_container["2"]; // array
for (let fd_email of fd_emails) {
//console.log(fd_email)
- const fd_email_id = fd_email["1"];
- const fd_legacy_email_id = fd_email["2"]["35"];
- const fd_email_smtp_id = fd_email["2"]["8"];
+ const fd_email_id = fd_email["0"];
+
+ // detailed to/from-fields must be obtained through the -other- email message node.
+ const fd_email2 = api.tools.parse_fd_request_payload_get_email2(fd_thread_container, fd_email_id);
+
+ const fd_legacy_email_id = fd_email["1"]["34"];
+ const fd_email_smtp_id = fd_email["1"]["7"];
- const fd_email_subject = fd_email["2"]["5"];
- const fd_email_timestamp = Number.parseInt(fd_email["2"]["17"]);
+ const fd_email_subject = fd_email["1"]["4"];
+ const fd_email_timestamp = Number.parseInt(fd_email["1"]["16"]);
const fd_email_date = new Date(fd_email_timestamp);
- const fd_attachments = api.tools.parse_fd_attachments(fd_email["2"]["14"]);
+ const fd_email_is_draft = api.tools.parse_fd_bv_is_draft(fd_email2["3"]);
- const fd_email_sender_address = fd_email["2"]["11"]["17"];
+ const fd_email_content_html = api.tools.parse_fd_request_html_payload(fd_email);
- const fd_to = api.tools.parse_fd_email(fd_email["2"]["1"]);
- const fd_cc = api.tools.parse_fd_email(fd_email["2"]["2"]);
- const fd_bcc = api.tools.parse_fd_email(fd_email["2"]["3"]);
+ const fd_attachments = api.tools.parse_fd_attachments(fd_email["1"]["13"]);
+
+ const fd_email_sender_address = fd_email["1"]["10"]["16"];
+
+ let fd_from = api.tools.parse_fd_bv_contact(fd_email2["1"]);
+ if (!fd_from) {
+ fd_from = { address: fd_email_sender_address, name: "" };
+ }
+
+ const fd_to = api.tools.parse_fd_bv_contacts(fd_email["1"]["0"]);
+ const fd_cc = api.tools.parse_fd_bv_contacts(fd_email["1"]["1"]);
+ const fd_bcc = api.tools.parse_fd_bv_contacts(fd_email["1"]["2"]);
const email = {
+ id: fd_email_id,
+ is_draft: fd_email_is_draft,
+ legacy_email_id: fd_legacy_email_id,
thread_id: fd_thread_id,
- email_id: fd_email_id,
+ smtp_id: fd_email_smtp_id,
+ subject: fd_email_subject,
+ timestamp: fd_email_timestamp,
+ content_html: fd_email_content_html,
+ date: fd_email_date,
+ from: fd_from,
+ to: fd_to,
+ cc: fd_cc,
+ bcc: fd_bcc,
+ attachments: fd_attachments
+ };
+ if (api.cache.debug_xhr_fetch) {
+ email["$email_node"] = fd_email;
+ email["$thread_node"] = fd_thread_container;
+ }
+ //console.log(email);
+ res.push(email);
+ }
+ }
+
+ return res;
+ }
+ catch (error) {
+ console.warn("Gmail.js encountered an error trying to parse email-data on fd request!", error);
+ return null;
+ }
+ };
+
+ api.tools.parse_fd_embedded_json = function (json) {
+ // ensure JSON-format is known and understood?
+ let thread_root = json["1"];
+
+ if (!thread_root || !Array.isArray(thread_root)) {
+ return null;
+ }
+
+ try {
+ const res = [];
+
+ const fd_threads = thread_root; // array
+ for (let fd_thread_container of fd_threads) {
+ const fd_thread_id = fd_thread_container["1"]["3"];
+
+ let fd_emails = fd_thread_container["1"]["4"]; // array
+ for (let fd_email of fd_emails) {
+ //console.log(fd_email)
+ const fd_email_id = fd_email["0"];
+
+
+
+ // detailed to/from-fields must be obtained through the -other- email message node.
+ //TODO : need a refactoring
+ const fd_email2 = api.tools.parse_fd_embedded_json_get_email(fd_thread_container, fd_email_id);
+
+
+ //TODO : to check...
+ const fd_legacy_email_id = fd_email["55"];
+ const fd_email_smtp_id = fd_email["13"];
+ const fd_email_subject = fd_email["7"];
+
+ const fd_email_is_draft = api.tools.parse_fd_bv_is_draft(fd_email["10"]);
+
+ //TODO : to check...
+ const fd_email_timestamp = Number.parseInt(fd_email["17"]);
+ const fd_email_date = new Date(fd_email_timestamp);
+
+ //TODO : need a refactoring
+ const fd_email_content_html = api.tools.parse_fd_embedded_json_content_html(fd_email);
+
+ const fd_attachments = api.tools.parse_fd_embedded_json_attachments(fd_email["11"]);
+ const fd_email_sender_address = fd_email["18"]["16"];
+
+ //TODO
+ let fd_from = api.tools.parse_fd_bv_contact(fd_email2["1"]);
+ if (!fd_from) {
+ fd_from = {
+ address: fd_email_sender_address,
+ name: ""
+ };
+ }
+
+ const fd_to = api.tools.parse_fd_bv_contacts(fd_email["2"]);
+ const fd_cc = api.tools.parse_fd_bv_contacts(fd_email["3"]);
+ const fd_bcc = api.tools.parse_fd_bv_contacts(fd_email["4"]);
+
+ const email = {
+ id: fd_email_id,
+ is_draft: fd_email_is_draft,
legacy_email_id: fd_legacy_email_id,
- email_smtp_id: fd_email_smtp_id,
- email_subject: fd_email_subject,
- email_timestamp: fd_email_timestamp,
- email_date: fd_email_date,
- email_sender_address: fd_email_sender_address,
- email_to: fd_to,
- email_cc: fd_cc,
- email_bcc: fd_bcc,
- email_attachments: fd_attachments,
- $data_node: fd_email
+ thread_id: fd_thread_id,
+ smtp_id: fd_email_smtp_id,
+ subject: fd_email_subject,
+ timestamp: fd_email_timestamp,
+ content_html: fd_email_content_html,
+ date: fd_email_date,
+ from: fd_from,
+ to: fd_to,
+ cc: fd_cc,
+ bcc: fd_bcc,
+ attachments: fd_attachments
+ };
+ if (api.cache.debug_xhr_fetch) {
+ email["$email_node"] = fd_email;
+ email["$thread_node"] = fd_thread_container;
+ }
+ //console.log(email);
+ res.push(email);
+ }
+ }
+
+ return res;
+ } catch (error) {
+ console.warn("Gmail.js encountered an error trying to parse email-data on embedded json!", error);
+ return null;
+ }
+ };
+
+ /**
+ * Parse xhr response fom bv request like https://mail.google.com/sync/u/0/i/bv?hl=fr&c=0
+ */
+ api.tools.parse_bv_request_payload = function (json) {
+ // ensure JSON-format is known and understood?
+ // JSON-format is not simple to understand, code here is bases on hypothesis
+ //let label_root = json["2"];
+ let thread_root = json["2"];
+ if (!thread_root || !Array.isArray(thread_root)) {
+ return null;
+ }
+
+ try {
+ const res = [];
+
+ const bv_threads = thread_root; // array
+ for (let bv_thread_container of bv_threads) {
+ const bv_thread_subject = bv_thread_container["0"]["0"];
+ const bv_thread_id = bv_thread_container["0"]["3"];
+
+ let bv_emails = bv_thread_container["0"]["4"]; // array
+ for (let bv_email of bv_emails) {
+ //console.log(bv_email)
+ const bv_email_id = bv_email["0"];
+ const bv_legacy_email_id = bv_email["55"];
+ const bv_email_smtp_id = ""; //bv_email["16"] is smtp_id of previous email in the conversation
+ //const bv_email["16"] !==undefined ? bv_email["16"] : ""; //present only if user is the sender ?
+ const bv_email_subject = bv_thread_subject; //value present on thread but not on email
+ const bv_email_timestamp = Number.parseInt(bv_email["17"]); //another timestamp with same value present on bv_email["31"]
+ const bv_email_date = new Date(bv_email_timestamp);
+ const bv_email_content_html = ""; //Not present in bv request
+
+ const bv_email_is_draft = api.tools.parse_fd_bv_is_draft(bv_email["10"]);
+
+ //TODO
+ const bv_attachments = []; //Present but need a new parser (not urgent, present in fd email)
+
+ //TODO : check if it's OK
+ const bv_from = {
+ address: bv_email["1"]["1"] !== undefined ? bv_email["1"]["1"] : "",
+ name: bv_email["1"]["2"] !== undefined ? bv_email["1"]["2"] : ""
};
+
+ const bv_to = []; //Not present in bv request
+ const bv_cc = []; //Not present in bv request
+ const bv_bcc = []; //Not present in bv request
+
+ const email = {
+ id: bv_email_id,
+ is_draft: bv_email_is_draft,
+ legacy_email_id: bv_legacy_email_id,
+ thread_id: bv_thread_id,
+ smtp_id: bv_email_smtp_id,
+ subject: bv_email_subject,
+ timestamp: bv_email_timestamp,
+ content_html: bv_email_content_html,
+ date: bv_email_date,
+ from: bv_from,
+ to: bv_to,
+ cc: bv_cc,
+ bcc: bv_bcc,
+ attachments: bv_attachments
+ };
+ if (api.cache.debug_xhr_fetch) {
+ email["$email_node"] = bv_email;
+ email["$thread_node"] = bv_thread_container;
+ }
//console.log(email);
res.push(email);
}
}
- return res;
+ return res;
+ } catch (error) {
+ console.warn("Gmail.js encountered an error trying to parse email-data on bv request!", error);
+ return null;
+ }
+ };
+
+ api.tools.parse_bv_embedded_json = function (json) {
+ // ensure JSON-format is known and understood?
+ // JSON-format is not simple to understand, code here is bases on hypothesis
+ let thread_root = json["0"]["0"];
+ if (!thread_root || !Array.isArray(thread_root)) {
+ return null;
+ }
+
+ try {
+ const res = [];
+
+ const bv_threads = thread_root; // array
+ for (let bv_thread_container of bv_threads) {
+ const bv_thread_subject = bv_thread_container["4"]["0"];
+ const bv_thread_id = bv_thread_container["4"]["3"];
+
+ let bv_emails = bv_thread_container["4"]["4"]; // array
+ for (let bv_email of bv_emails) {
+ //console.log(bv_email)
+ const bv_email_id = bv_email["0"];
+ const bv_legacy_email_id = bv_email["55"];
+ const bv_email_smtp_id = ""; //bv_email["16"] is smtp_id of previous email in the conversation
+ //const bv_email["16"] !==undefined ? bv_email["16"] : ""; //present only if user is the sender ?
+ const bv_email_subject = bv_thread_subject; //value present on thread but not on email
+ const bv_email_timestamp = Number.parseInt(bv_email["17"]); //another timestamp with same value present on bv_email["31"]
+ const bv_email_date = new Date(bv_email_timestamp);
+ const bv_email_content_html = ""; //Not present in bv request
+
+ const bv_email_is_draft = api.tools.parse_fd_bv_is_draft(bv_email["10"]);
+
+ //TODO
+ const bv_attachments = []; //Present but need a new parser (not urgent, present in fd email)
+
+ //TODO : check if it's OK
+ const bv_from = {
+ address: bv_email["1"]["1"] !== undefined ? bv_email["1"]["1"] : "",
+ name: bv_email["1"]["2"] !== undefined ? bv_email["1"]["2"] : ""
+ };
+
+ const bv_to = []; //Not present in bv request
+ const bv_cc = []; //Not present in bv request
+ const bv_bcc = []; //Not present in bv request
+
+ const email = {
+ id: bv_email_id,
+ is_draft: bv_email_is_draft,
+ legacy_email_id: bv_legacy_email_id,
+ thread_id: bv_thread_id,
+ smtp_id: bv_email_smtp_id,
+ subject: bv_email_subject,
+ timestamp: bv_email_timestamp,
+ content_html: bv_email_content_html,
+ date: bv_email_date,
+ from: bv_from,
+ to: bv_to,
+ cc: bv_cc,
+ bcc: bv_bcc,
+ attachments: bv_attachments
+ };
+ if (api.cache.debug_xhr_fetch) {
+ email["$email_node"] = bv_email;
+ email["$thread_node"] = bv_thread_container;
+ }
+ //console.log(email);
+ res.push(email);
+ }
+ }
+
+ return res;
+ } catch (error) {
+ console.warn("Gmail.js encountered an error trying to parse email-data on bv request!", error);
+ return null;
+ }
+
+
+ };
+
+
+ api.tools.parse_sent_message_html_payload = function(sent_email) {
+ let sent_email_content_html = null;
+ try {
+ const sent_html_containers = sent_email["9"]["2"];
+
+ for (let sent_html_container of sent_html_containers) {
+ sent_email_content_html = (sent_email_content_html || "") + sent_html_container["2"];
+ }
+ }
+ catch(e) {
+ // don't crash gmail when we cant parse email-contents
+ }
+
+ return sent_email_content_html;
+ };
+
+ api.tools.parse_sent_message_attachments = function(json) {
+ let res = [];
+
+ if (Array.isArray(json)) {
+ for (let item of json) {
+
+ res.push({
+ id: item["5"],
+ name: item["2"],
+ type: item["1"],
+ url: item["6"],
+ size: Number.parseInt(item["3"])
+ });
+ }
+ }
+
+ return res;
+ };
+
+ api.tools.parse_sent_message_payload = function(json) {
+ try
+ {
+ let sent_email = json;
+ //console.log(sent_email);
+
+ const sent_email_id = sent_email["0"];
+
+ const sent_email_subject = sent_email["7"];
+ const sent_email_timestamp = Number.parseInt(sent_email["6"]);
+ const sent_email_date = new Date(sent_email_timestamp);
+
+ const sent_email_content_html = api.tools.parse_sent_message_html_payload(sent_email);
+ const sent_email_ishtml = sent_email["8"]["6"];
+
+ const sent_attachments = api.tools.parse_sent_message_attachments(sent_email["11"]);
+
+ const sent_from = api.tools.parse_fd_bv_contact(sent_email["1"]);
+ const sent_to = api.tools.parse_fd_bv_contacts(sent_email["2"]);
+ const sent_cc = api.tools.parse_fd_bv_contacts(sent_email["3"]);
+ const sent_bcc = api.tools.parse_fd_bv_contacts(sent_email["4"]);
+
+ const email = {
+ 1: sent_email_id,
+ id: sent_email_id,
+ subject: sent_email_subject,
+ timestamp: sent_email_timestamp,
+ content_html: sent_email_content_html,
+ ishtml: sent_email_ishtml,
+ date: sent_email_date,
+ from: sent_from,
+ to: sent_to,
+ cc: sent_cc,
+ bcc: sent_bcc,
+ attachments: sent_attachments,
+ email_node: json
+ };
+
+ return email;
+ }
+ catch (error) {
+ console.warn("Gmail.js encountered an error trying to parse sent message!", error);
+ return null;
+ }
+ };
+
+ api.tools.parse_sent_message_payload_new = function(json) {
+ try
+ {
+ const parse_fd_bv_contact_new = (a) => {
+ if (a && a[1]) {
+ return { name: a[2] || "", address: a[1] };
+ } else {
+ return undefined;
+ }
+ };
+
+ const parse_fd_bv_contacts_new = (a) => {
+ if (Array.isArray(a)) {
+ return a.map(parse_fd_bv_contact_new).filter(a => a);
+ } else {
+ return [];
+ }
+ };
+
+ const parse_sent_message_attachments_new = (json) => {
+ if (Array.isArray(json)) {
+ return json.map(item => ({
+ id: item[4],
+ name: item[1],
+ type: item[0],
+ url: item[5],
+ size: Number.parseInt(item[2])
+ }));
+ } else {
+ return [];
+ }
+ };
+
+ const parse_sent_message_html_payload_new = (sent_email) => {
+ let sent_email_content_html = null;
+ try {
+ const sent_html_containers = sent_email[8][1];
+ for (let sent_html_container of sent_html_containers) {
+ sent_email_content_html = (sent_email_content_html || "") + sent_html_container[1];
+ }
+ } catch(err) {
+ // don't crash gmail when we cant parse email-contents
+ api.tools.error("Failed to parse html", err);
+ }
+
+ return sent_email_content_html;
+ };
+
+ let sent_email = json;
+ //console.log(sent_email);
+
+ const sent_email_id = sent_email[0];
+
+ const sent_email_subject = sent_email[7];
+ const sent_email_timestamp = sent_email[6];
+ const sent_email_date = new Date(sent_email_timestamp);
+
+ const sent_email_content_html = parse_sent_message_html_payload_new(sent_email);
+ const sent_email_ishtml = sent_email[8][6];
+ const sent_attachments = parse_sent_message_attachments_new(sent_email[11]);
+
+ const sent_from = parse_fd_bv_contact_new(sent_email[1]);
+ const sent_to = parse_fd_bv_contacts_new(sent_email[2]);
+ const sent_cc = parse_fd_bv_contacts_new(sent_email[3]);
+ const sent_bcc = parse_fd_bv_contacts_new(sent_email[4]);
+
+ const email = {
+ 1: sent_email_id,
+ id: sent_email_id,
+ subject: sent_email_subject,
+ timestamp: sent_email_timestamp,
+ content_html: sent_email_content_html,
+ ishtml: sent_email_ishtml,
+ date: sent_email_date,
+ from: sent_from,
+ to: sent_to,
+ cc: sent_cc,
+ bcc: sent_bcc,
+ attachments: sent_attachments,
+ email_node: json
+ };
+
+ return email;
}
catch (error) {
- console.warn("Gmail.js encountered an error trying to parse email-data!", error);
+ console.warn("Gmail.js encountered an error trying to parse sent message!", error);
return null;
}
};
@@ -1305,9 +1856,11 @@ var Gmail = function(localJQuery) {
const threads = api.tools.extract_from_graph(params, api.check.data.is_thread);
// console.log("Threads:");
// console.log(threads);
- const emails = api.tools.extract_from_graph(params, api.check.data.is_email);
- // console.log("Emails:");
- // console.log(emails);
+ const emails = [
+ ...api.tools.extract_from_graph(params.body_params, api.check.data.is_email),
+ ...api.tools.extract_from_graph(params.body_params, api.check.data.is_email_new),
+ ];
+ // console.log("Emails:", emails, "url", params.url_raw, "body", params.body_params);
for (let email of emails) {
// console.log("Email:");
@@ -1315,10 +1868,13 @@ var Gmail = function(localJQuery) {
for (let key in email) {
let prop = email[key];
if (api.check.data.is_smartlabels_array(prop)) {
+ let sent_email = api.check.data.is_email_new(email) ?
+ api.tools.parse_sent_message_payload_new(email) :
+ api.tools.parse_sent_message_payload(email);
if (prop.indexOf("^pfg") !== -1) {
- // TODO: parse `email` for contents, and provide a better strucutred
- // object
- events.send_message = [params.url, params.body, email];
+ events.send_message = [params.url, params.body, sent_email];
+ } else if (prop.indexOf("^scheduled") > -1) {
+ events.send_scheduled_message = [params.url, params.body, sent_email];
}
}
}
@@ -1357,7 +1913,7 @@ var Gmail = function(localJQuery) {
// dont crash on those.
if (response.startsWith(" i.thread_id === threadId);
- let firstEmail = emails[0];
- if (firstEmail) {
- let thread_id = firstEmail.thread_id;
- let thread = c.threadCache[thread_id];
- if (!thread) {
- thread = {
- thread_id: thread_id,
- emails: []
- };
- c.threadCache[thread_id] = thread;
- }
+ // ensure we have a thread-object before appending emails to it!
+ let thread = c.threadCache[email.thread_id];
+ if (!thread) {
+ thread = {
+ thread_id: email.thread_id,
+ emails: []
+ };
+ c.threadCache[email.thread_id] = thread;
+ }
- for (let email of emails) {
- if (thread.emails.filter(i => i.email_id === email.email_id).length === 0) {
- thread.emails.push(email);
- }
- }
+ // only append email to cache if not already there.
+ if (thread.emails.filter(i => i.id === email.id).length === 0) {
+ //console.log("append email to thread cache",data_source, email) ;
+ thread.emails.push(email);
+ }
+ // Only update cache with data source fd_request_payload and fd_embedded_json
+ else if (isUpdateAuthorized) {
+ let index = thread.emails.findIndex(i => i.id === email.id);
+ //console.log("update email in thread cache",data_source,email);
+ thread.emails[index] = email;
}
}
};
@@ -1521,6 +2091,7 @@ var Gmail = function(localJQuery) {
return;
}
+ api.instanceId = Symbol('gmail-js-' + (performance ? performance.now() : Date.now()));
api.tracker.xhr_init = true;
const win = api.helper.get_xhr_window();
@@ -1532,6 +2103,12 @@ var Gmail = function(localJQuery) {
method: method.toString(),
url: url.toString()
};
+ Object.defineProperty(this, api.instanceId, {
+ value: Object.freeze({
+ method: method.toString(),
+ url: url.toString()
+ })
+ });
return out;
};
});
@@ -1542,24 +2119,40 @@ var Gmail = function(localJQuery) {
var events = false;
if (this.xhrParams) {
this.xhrParams.body = body;
+
+ // restore original values of xhrParams, if they were altered by upstream instances of gmail.js
+ if (typeof this.xhrParams.url !== 'string') {
+ if (
+ this[api.instanceId]
+ && this[api.instanceId].url
+ ) {
+ this.xhrParams.url = this[api.instanceId].url;
+ delete this.xhrParams.url_raw;
+ delete this.xhrParams.body_params;
+ }
+ }
+
events = api.tools.parse_requests(this.xhrParams, this);
}
// fire before events
- if(api.observe.trigger("before", events, this)) {
-
+ if (api.observe.trigger("before", events, this)) {
// if before events were fired, rebuild arguments[0]/body strings
// TODO: recreate the url if we want to support manipulating url args (is there a use case where this would be needed?)
if (api.check.is_new_data_layer()) {
- body = arguments[0] = this.xhrParams.body_is_object ? this.xhrParams.body_params : JSON.stringify(this.xhrParams.body_params);
+ body = arguments[0] = this.xhrParams.body_is_object
+ ? this.xhrParams.body_params
+ : JSON.stringify(this.xhrParams.body_params);
} else {
- body = arguments[0] = this.xhrParams.body_is_object ? this.xhrParams.body_params : $.param(this.xhrParams.body_params,true).replace(/\+/g, "%20");
+ body = arguments[0] = this.xhrParams.body_is_object
+ ? this.xhrParams.body_params
+ : $.param(this.xhrParams.body_params,true).replace(/\+/g, "%20");
}
}
// if any matching after events, bind onreadystatechange callback
- // also: on new gmail we want to intercept email-data from /i/fd-request responses.
- if(api.observe.bound(events, "after") || api.check.is_new_data_layer()) {
+ // also: on new gmail we want to intercept email-data from /i/fd or /i/bv request responses.
+ if (api.observe.bound(events, "after") || api.check.is_new_data_layer()) {
var curr_onreadystatechange = this.onreadystatechange;
var xhr = this;
this.onreadystatechange = function(progress) {
@@ -1573,10 +2166,20 @@ var Gmail = function(localJQuery) {
// intercept email-data passively, instead of actively trying to fetch it later!
// (which we won't be able to do once 2019 hits anyway...)
if (api.check.is_new_data_layer()) {
- if (api.tools.get_pathname_from_url(http://github.com/xhr.xhrParams.url_raw).endsWith("/i/fd")) {
+ const pathName = api.tools.get_pathname_from_url(http://github.com/xhr.xhrParams.url_raw);
+ if (pathName.endsWith("/i/fd")) {
let parsed_emails = api.tools.parse_fd_request_payload(xhr.xhrResponse);
- api.tools.cache_email_data(parsed_emails);
- events.load_email_data = [parsed_emails];
+ if (parsed_emails !== undefined && parsed_emails !== null) {
+ api.tools.cache_email_data(parsed_emails,"fd_request_payload");
+ events.load_email_data = [parsed_emails];
+ }
+ }
+ if (pathName.endsWith("/i/bv")) {
+ let parsed_emails = api.tools.parse_bv_request_payload(xhr.xhrResponse);
+ if (parsed_emails !== undefined && parsed_emails !== null) {
+ api.tools.cache_email_data(parsed_emails,"bv_request_payload");
+ events.load_email_data = [parsed_emails];
+ }
}
}
api.observe.trigger("after", events, xhr);
@@ -1597,27 +2200,76 @@ var Gmail = function(localJQuery) {
});
};
+ api.tools.embedded_data_watcher = function() {
+
+ if (api.tracker.embedded_data_init) {
+ return;
+ }
+
+ api.tracker.embedded_data_init = true;
+
+ var original_GM_setData = window._GM_setData;
+ window._GM_setData = function(data) {
+
+ if (data !== undefined && data.Cl6csf !== undefined && data.Cl6csf[0] !== undefined && data.Cl6csf[0][2] !== undefined) {
+ //console.log('Cl6csf',JSON.parse(data.Cl6csf[0][2]));
+ let parsed_emails = api.tools.parse_fd_embedded_json(JSON.parse(data.Cl6csf[0][2]));
+ api.tools.cache_email_data(parsed_emails,"fd_embedded_json");
+ //TODO : event is not load yet at this time of workflow, addon is necessary to observe load email event for this case
+ //events.load_email_data = [parsed_emails];
+
+ }
+ if (data !== undefined && data.a6jdv !== undefined && data.a6jdv[0] !== undefined && data.a6jdv[0][2] !== undefined) {
+ //console.log('a6jdv',JSON.parse(data.a6jdv[0][2]));
+ let parsed_emails = api.tools.parse_bv_embedded_json(JSON.parse(data.a6jdv[0][2]));
+ api.tools.cache_email_data(parsed_emails,"bv_embedded_json");
+ //TODO : event is not load yet at this time of workflow, addon is necessary to observe load email event for this case
+ //events.load_email_data = [parsed_emails];
+
+ }
+ if (data !== undefined && data.sBEv4c !== undefined) {
+ for (let item of data.sBEv4c) {
+ // the index of the mla is not confirmed to be stable
+ // it was observed to be at position 3, but we should not depend on it
+ if (item[0] === "mla") {
+ api.tracker.mla = item;
+ }
+ }
+ }
+
+ original_GM_setData(data);
+ };
+ };
+
api.helper.get_xhr_window = function() {
- var js_frame = null;
+ // in the new gmail UI, in the case of window_opener as xhr window,
+ // some events do not work, for example before_send event
+ if (api.check.is_new_gui()) {
+ return top;
+ }
+ var js_frame = null;
if (top.document.getElementById("js_frame")){
js_frame = top.document.getElementById("js_frame");
- } else if (window.opener) {
- js_frame = window.opener.top.document.getElementById("js_frame");
+ } else if (window_opener) {
+ js_frame = window_opener.top.document.getElementById("js_frame");
}
+
if (!js_frame){
- if (window.opener) {
- js_frame = window.opener.top;
+ if (window_opener) {
+ js_frame = window_opener.top;
} else {
js_frame = top;
}
}
+
var win;
if (js_frame.contentDocument) {
win = js_frame.contentDocument.defaultView;
} else {
win = js_frame;
}
+
return win;
};
@@ -1711,9 +2363,9 @@ var Gmail = function(localJQuery) {
// if an object of actions (triggered events of format { event: [response] }) is passed, check if any of these are bound
if(typeof action === "object") {
var match = false;
- $.each(action,function(key,response){
+ for (let key of Object.keys(action)) {
if(typeof api.tracker.watchdog[type][key] === "object") match = true;
- });
+ }
return match;
}
if(type) return typeof api.tracker.watchdog[type][action] === "object";
@@ -1736,8 +2388,8 @@ var Gmail = function(localJQuery) {
// loop through applicable types
var types = type ? [ type ] : [ "before", "on", "after", "dom" ];
- $.each(types, function(idx, type) {
- if(typeof api.tracker.watchdog[type] !== "object") return true; // no callbacks for this type
+ for (let type of types) {
+ if(typeof api.tracker.watchdog[type] !== "object") continue; // no callbacks for this type
// if action specified, remove any callbacks for this action, otherwise remove all callbacks for all actions
if(action) {
@@ -1747,15 +2399,15 @@ var Gmail = function(localJQuery) {
delete api.tracker.watchdog[type][action];
}
} else {
- $.each(api.tracker.watchdog[type], function(act,callbacks) {
+ for (let act of Object.keys(api.tracker.watchdog[type])) {
if(typeof api.tracker.watchdog[type][act] === "object") {
api.tracker.bound[act] -= api.tracker.watchdog[type][act].length;
api.tracker.bound[type] -= api.tracker.watchdog[type][act].length;
delete api.tracker.watchdog[type][act];
}
- });
+ }
}
- });
+ }
};
/**
@@ -1765,19 +2417,19 @@ var Gmail = function(localJQuery) {
api.observe.trigger = function(type, events, xhr) {
if(!events) return false;
var fired = false;
- $.each(events, function(action,response) {
+ for (let [action, response] of Object.entries(events)) {
// we have to do this here each time to keep backwards compatibility with old response_callback implementation
- response = $.extend([], response); // break the reference so it doesn"t keep growing each trigger
+ response = [...response]; // break the reference so it doesn't keep growing each trigger
if(type === "after") response.push(xhr.xhrResponse); // backwards compat for after events requires we push onreadystatechange parsed response first
response.push(xhr);
if(api.observe.bound(action, type)) {
fired = true;
- $.each(api.tracker.watchdog[type][action], function(idx, callback) {
+ for (let callback of api.tracker.watchdog[type][action]) {
callback.apply(undefined, response);
- });
+ }
}
- });
+ }
return fired;
};
@@ -1795,9 +2447,9 @@ var Gmail = function(localJQuery) {
if (!api.tracker.watchdog.dom[observer]) {
return;
}
- $.each(api.tracker.watchdog.dom[observer], function(idx, callback) {
+ for (let callback of api.tracker.watchdog.dom[observer]) {
handler(element, callback);
- });
+ }
};
// pre-configured DOM observers
@@ -1824,7 +2476,7 @@ var Gmail = function(localJQuery) {
// which is triggered by the XHR request rather than nodes being inserted into the DOM (and thus returns different information)
"view_thread": {
class: ["Bu", "nH"], // class depends if is_preview_pane - Bu for preview pane, nH for standard view
- sub_selector: "div.if",
+ selector: "div.iY",
handler: function(match, callback) {
match = new api.dom.thread(match);
callback(match);
@@ -1834,19 +2486,23 @@ var Gmail = function(localJQuery) {
// when an individual email is loaded within a thread (also fires when thread loads displaying the latest email)
"view_email": {
// class depends if is_preview_pane - Bu for preview pane, nH for standard view,
- // the empty class ("") is for emails opened after thread is rendered.
+ // FIXME: the empty class ("") is for emails opened after thread is rendered (causes a storm of updates)
class: ["Bu", "nH", ""],
- sub_selector: "div.adn",
handler: function(match, callback) {
- match = new api.dom.email(match);
- callback(match);
+ setTimeout(() => {
+ match = match.find("div.adn.ads");
+ if (match.length) {
+ match = new api.dom.email(match);
+ callback(match);
+ }
+ }, 0);
}
},
// when the dropdown menu next to the reply button is inserted into the DOM when viewing an email
"load_email_menu": {
class: "J-N",
- selector: "div[role=menu] div[role=menuitem]:first-child", // use the first menu item in the popoup as the indicator to trigger this observer
+ selector: "div[role=menu] div[role=menuitem]:first-child", // use the first menu item in the popup as the indicator to trigger this observer
handler: function(match, callback) {
match = match.closest("div[role=menu]");
callback(match);
@@ -1855,7 +2511,7 @@ var Gmail = function(localJQuery) {
// a new email address is added to any of the to,cc,bcc fields when composing a new email or replying/forwarding
"recipient_change": {
- class: "vR",
+ class: ["vR", "afV"],
handler: function(match, callback) {
// console.log("compose:recipient handler called",match,callback);
@@ -1870,8 +2526,19 @@ var Gmail = function(localJQuery) {
// console.log("recipient timeout handler", api.tracker.recipient_matches.length);
if(!api.tracker.recipient_matches.length) return;
+ let composeRoot = [];
+ // sometimes (on copy-paste of contact in peoplekit mode) element disappears so iterate for all matches
+ api.tracker.recipient_matches.forEach(match => {
+ if (composeRoot.length === 0) {
+ composeRoot = match.closest("div.M9");
+ }
+ });
+
+ if (composeRoot.length === 0) {
+ api.tools.error("Can't find composeRoot for " + match);
+ }
+ var compose = new api.dom.compose(composeRoot);
// determine an array of all emails specified for To, CC and BCC and extract addresses into an object for the callback
- var compose = new api.dom.compose(api.tracker.recipient_matches[0].closest("div.M9"));
var recipients = compose.recipients();
callback(compose, recipients, api.tracker.recipient_matches);
@@ -1893,12 +2560,7 @@ var Gmail = function(localJQuery) {
match = match.closest("div.M9");
if (!match.length) return;
match = new api.dom.compose(match);
- var type;
- if (match.is_inline()) {
- type = match.find("input[name=subject]").val().indexOf("Fw") === 0 ? "forward" : "reply";
- } else {
- type = "compose";
-
+ if (!match.is_inline()) {
//Find the close button and set an event listener so we can forward the compose_cancelled event.
var composeWindow = originalMatch.closest("div.AD");
composeWindow.find(".Ha").mouseup(function() {
@@ -1907,9 +2569,8 @@ var Gmail = function(localJQuery) {
}
return true;
});
-
}
- callback(match,type);
+ callback(match, match.type());
}
}
};
@@ -1922,15 +2583,15 @@ var Gmail = function(localJQuery) {
// map observed classNames to actions
api.tracker.dom_observer_map = {};
- $.each(api.tracker.dom_observers, function(act,config){
- if(!$.isArray(config.class)) config.class = [config.class];
- $.each(config.class, function(idx, className) {
+ for (let [act, config] of Object.entries(api.tracker.dom_observers)) {
+ if (!Array.isArray(config.class)) config.class = [config.class];
+ for (let className of config.class) {
if (!api.tracker.dom_observer_map[className]) {
api.tracker.dom_observer_map[className] = [];
}
api.tracker.dom_observer_map[className].push(act);
- });
- });
+ }
+ }
//console.log( "observer_config", api.tracker.dom_observers, "dom_observer_map", api.tracker.dom_observer_map);
};
@@ -1956,14 +2617,14 @@ var Gmail = function(localJQuery) {
// was an object of arguments passed, or just a className
var config = {};
- if (typeof args === "object" && !$.isArray(args)) {
+ if (typeof args === "object" && !Array.isArray(args)) {
// copy over supported config
- $.each(["class","selector","sub_selector","handler"], function(idx, arg) {
+ for (let arg of ["class", "selector", "sub_selector", "handler"]) {
if(args[arg]) {
config[arg] = args[arg];
}
- });
+ }
} else {
config["class"] = args;
}
@@ -1971,6 +2632,34 @@ var Gmail = function(localJQuery) {
api.tracker.custom_dom_observers[action] = config;
};
+ var getTarget = function(e) {
+ // firefox does not support e.path
+ if (e.path) {
+ return e.path[0];
+ } else {
+ return e.target;
+ }
+ };
+
+ // prevent gmail jacking our click-events!
+ var preventGmailJacking = function() {
+ // install event-handler only once!
+ if (!api.tracker.jackPreventionInstalled) {
+ window.addEventListener("click", (e) => {
+ const target = getTarget(e);
+ if (target && target !== document.body) {
+ const gmailJsButton = target.querySelector(":scope > .gmailjs");
+ if (gmailJsButton) {
+ gmailJsButton.click();
+ e.preventDefault();
+ }
+ }
+ });
+ api.tracker.jackPreventionInstalled = true;
+ }
+ };
+
+
/**
Observe DOM nodes being inserted. When a node with a class defined in api.tracker.dom_observers is inserted,
trigger the related event and fire off any relevant bound callbacks
@@ -1984,7 +2673,7 @@ var Gmail = function(localJQuery) {
}
// support for DOM observers
- if($.inArray(action, api.tracker.supported_observers) > -1) {
+ if (api.tracker.supported_observers.includes(action)) {
//console.log("observer found",api.tracker.dom_observers[action]);
@@ -1993,13 +2682,6 @@ var Gmail = function(localJQuery) {
api.tracker.observing_dom = true;
//api.tracker.dom_watchdog = {}; // store passed observer callbacks for different DOM events
- // this listener will check every element inserted into the DOM
- // for specified classes (as defined in api.tracker.dom_observers above) which indicate
- // related actions which need triggering
- $(window.document).on("DOMNodeInserted", function(e) {
- api.tools.insertion_observer(e.target, api.tracker.dom_observers, api.tracker.dom_observer_map);
- });
-
// recipient_change also needs to listen to removals
var mutationObserver = new MutationObserver(function(mutations) {
for (var i = 0; i < mutations.length; i++) {
@@ -2007,11 +2689,25 @@ var Gmail = function(localJQuery) {
var removedNodes = mutation.removedNodes;
for (var j = 0; j < removedNodes.length; j++) {
var removedNode = removedNodes[j];
- if (removedNode.className === "vR") {
- var observer = api.tracker.dom_observer_map["vR"];
- var handler = api.tracker.dom_observers.recipient_change.handler;
+ if (removedNode.className === "agh" && removedNode.querySelector("div[data-hovercard-id]")) { // contains recipient in peoplekit
+ let observer = api.tracker.dom_observer_map["afV"];
+ let handler = api.tracker.dom_observers.recipient_change.handler;
api.observe.trigger_dom(observer, $(mutation.target), handler);
- }
+ } else
+ if (removedNode.className === "vR") {
+ let observer = api.tracker.dom_observer_map["vR"];
+ let handler = api.tracker.dom_observers.recipient_change.handler;
+ api.observe.trigger_dom(observer, $(mutation.target), handler);
+ }
+ }
+
+ // this listener will check every element inserted into the DOM
+ // for specified classes (as defined in api.tracker.dom_observers above) which indicate
+ // related actions which need triggering
+ var addedNodes = mutation.addedNodes;
+ for (var k = 0; k < addedNodes.length; k++) {
+ var addedNode = addedNodes[k];
+ api.tools.insertion_observer(addedNode, api.tracker.dom_observers, api.tracker.dom_observer_map);
}
}
});
@@ -2025,15 +2721,19 @@ var Gmail = function(localJQuery) {
// support for gmail interface load event
}
else if(action === "compose_cancelled") {
- console.log("set compose cancelled callback");
+ //console.log("set compose cancelled callback");
api.tracker.composeCancelledCallback = callback;
+ return true;
}
else if(action === "load") {
// wait until the gmail interface has finished loading and then
// execute the passed handler. If interface is already loaded,
// then will just execute callback
- if(api.dom.inbox_content().length) return callback();
+ if(api.dom.inbox_content().length) {
+ preventGmailJacking();
+ return callback();
+ }
var load_count = 0;
var delay = 200; // 200ms per check
var attempts = 50; // try 50 times before giving up & assuming an error
@@ -2041,43 +2741,45 @@ var Gmail = function(localJQuery) {
var test = api.dom.inbox_content().length;
if(test > 0) {
clearInterval(timer);
+ preventGmailJacking();
return callback();
} else if(++load_count > attempts) {
clearInterval(timer);
- console.log("Failed to detect interface load in " + (delay*attempts/1000) + " seconds. Will automatically fire event in 5 further seconds.");
+ //console.log("Failed to detect interface load in " + (delay*attempts/1000) + " seconds. Will automatically fire event in 5 further seconds.");
setTimeout(callback, 5000);
}
}, delay);
return true;
}
+ return false;
};
// observes every element inserted into the DOM by Gmail and looks at the classes on those elements,
// checking for any configured observers related to those classes
api.tools.insertion_observer = function(target, dom_observers, dom_observer_map, sub) {
//console.log("insertion", target, target.className);
- if(!api.tracker.dom_observer_map) return;
+ if(!dom_observer_map) return;
// loop through each of the inserted elements classes & check for a defined observer on that class
var cn = target.className || "";
var classes = cn.trim ? cn.trim().split(/\s+/) : [];
if(!classes.length) classes.push(""); // if no class, then check for anything observing nodes with no class
- $.each(classes, function(idx, className) {
+ for (let className of classes) {
var observers = dom_observer_map[className];
if (!observers) {
- return;
+ continue;
}
for (var observer of observers) {
// check if this is a defined observer, and callbacks are bound to that observer
- if(observer && api.tracker.watchdog.dom[observer]) {
+ if(observer && api.tracker.watchdog && api.tracker.watchdog.dom[observer]) {
var element = $(target);
var config = dom_observers[observer];
// if a config id specified for this observer, ensure it matches for this element
if(config.selector && !element.is(config.selector)) {
- return;
+ break;
}
// check for any defined sub_selector match - if not found, then this is not a match for this observer
@@ -2096,7 +2798,7 @@ var Gmail = function(localJQuery) {
}
}
}
- });
+ }
};
@@ -2226,8 +2928,13 @@ var Gmail = function(localJQuery) {
};
+ /**
+ * Checks if Gmail is opened for a delegated account.
+ *
+ * @returns {boolean}
+ */
api.helper.get.is_delegated_inbox = function() {
- return $(".identityUserDelegatedAccount").length === 1;
+ return $(".gb_Ba a.gb_f svg").length === 1;
};
@@ -2317,24 +3024,6 @@ var Gmail = function(localJQuery) {
return emails;
};
- // dispatch mousedown and mouseup event on passed element
- api.helper.trigger_mouse_click = function(element) {
- if(element) {
- //Trigger mouse down event
- var mouseDown = document.createEvent("MouseEvents");
- mouseDown.initEvent( "mousedown", true, false );
- element.dispatchEvent(mouseDown);
-
- //Trigger mouse up event
- var mouseUp = document.createEvent("MouseEvents");
- mouseUp.initEvent( "mouseup", true, false );
- element.dispatchEvent(mouseUp);
-
- return true;
- }
- return false;
- };
-
api.get.visible_emails = function(customInboxQuery) {
var url = api.helper.get.visible_emails_pre(customInboxQuery);
var get_data = api.tools.make_request(url);
@@ -2417,11 +3106,11 @@ var Gmail = function(localJQuery) {
if(typeof time !== "undefined"){
var initialInfoboxStyle = top.attr("style"); // backup initial style
top.removeAttr("style").fadeTo(time, 0, function(){ // simply remove then restore
- $(this).attr("style", initialInfoboxStyle); // style attribute insteed of playing
+ $(this).attr("style", initialInfoboxStyle); // style attribute instead of playing
}); // on visibility property
}
else{
- top.removeAttr("style"); // dito
+ top.removeAttr("style"); // ditto
}
}
};
@@ -2564,6 +3253,8 @@ var Gmail = function(localJQuery) {
api.helper.get.email_data_pre = function(thread_id) {
+ oldGmailApiDeprecated("Migrate code to use gmail.new.get.email_data() to fix this problem.");
+
if(api.check.is_inside_email() && thread_id === undefined) {
thread_id = api.get.thread_id();
}
@@ -2614,22 +3305,142 @@ var Gmail = function(localJQuery) {
};
- api.helper.get.email_source_pre = function(email_id) {
- if(!email_id && api.check.is_inside_email()) {
- email_id = api.get.email_id();
+ api.helper.get.legacy_email_id = function(identifier) {
+ if (!identifier) {
+ return null;
+ } else if (api.check.data.is_legacy_email_id(identifier)) {
+ return identifier;
+ } else if (identifier.legacy_email_id) {
+ return identifier.legacy_email_id;
+ } else if (api.check.data.is_email_id(identifier)) {
+ console.warn("GmailJS: Warning! Using new-style ID in method expecting legacy-style IDs! Attempting to resolve via cache, but there's no guarantee this will work!");
+ const emailData = api.cache.emailIdCache[identifier];
+ return emailData && emailData.legacy_email_id;
+ }
+
+ // DOMEmail
+ if (identifier.$el && identifier.$el[0]) {
+ identifier = identifier.$el[0]; // fallback to element-lookup.
+ }
+
+ // HTML Element
+ if (identifier.dataset && identifier.dataset.legacyMessageId) {
+ return identifier.dataset.legacyMessageId;
+ }
+
+ return null;
+ };
+
+ api.helper.get.new_email_id = function(identifier) {
+ if (!identifier) {
+ return null;
+ } else if (api.check.data.is_email_id(identifier)) {
+ return identifier;
+ } else if (identifier.id && !identifier.$el) { // ensure to only email_data, not DomEmail!
+ return identifier.id;
+ } else if (api.check.data.is_legacy_email_id(identifier)) {
+ console.warn("GmailJS: Warning! Using legacy-style ID in method expecting new-style IDs! Attempting to resolve via cache, but there's no guarantee this will work!");
+ const emailData = api.cache.emailLegacyIdCache[identifier];
+ return emailData && emailData.id;
+ }
+
+ // DOMEmail
+ if (identifier.$el && identifier.$el[0]) {
+ identifier = identifier.$el[0]; // fallback to element-lookup.
+ }
+
+ // HTML Element
+ if (identifier.dataset && identifier.dataset.messageId) {
+ let id = identifier.dataset.messageId;
+ if (id.indexOf("#") === 0) {
+ id = id.substring(1);
+ }
+
+ return id;
}
- if(!email_id) {
+ return null;
+ };
+
+ api.helper.get.thread_id = function(identifier) {
+ if (!identifier) {
return null;
+ } else if (api.check.data.is_thread_id(identifier)) {
+ return identifier;
+ } else if (identifier.thread_id) { // NewEmailData
+ return identifier.thread_id;
+ } else if (api.check.data.is_email_id(identifier)) {
+ console.warn("GmailJS: Warning! Using email-ID in method expecting thread-ID! Attempting to resolve via cache, but there's no guarantee this will work!");
+ const emailData = api.cache.emailIdCache[identifier];
+ return emailData && emailData.thread_id;
+ } else if (api.check.data.is_legacy_email_id(identifier)) {
+ console.warn("GmailJS: Warning! Using legacy-style ID in method expecting thread-ID! Attempting to resolve via cache, but there's no guarantee this will work!");
+ const emailData = api.cache.emailLegacyIdCache[identifier];
+ return emailData && emailData.thread_id;
+ }
+
+ // DOMEmail or DOMThread
+ if (identifier.$el && identifier.$el[0]) {
+ identifier = identifier.$el[0]; // fallback to element-lookup.
+ }
+
+ // HTML Element - Thread
+ if (identifier.dataset && identifier.dataset.threadPermId) {
+ let id = identifier.dataset.threadPermId;
+ if (id.indexOf("#") === 0) {
+ id = id.substring(1);
+ }
+
+ return id;
+ }
+
+ // HTML Element - Email
+ if (identifier.dataset && identifier.dataset.messageId) {
+ let id = identifier.dataset.messageId;
+ if (id.indexOf("#") === 0) {
+ id = id.substring(1);
+ }
+
+ console.warn("GmailJS: Warning! Using DomEmail instance to lookup thread-ID. Attempting to resolve via cache, but there's no guarantee this will work!");
+ const emailData = api.cache.emailIdCache[id];
+ return emailData && emailData.thread_id;
+ }
+
+ return null;
+ };
+
+ api.helper.clean_thread_id = function(thread_id) {
+ // handle new gmail style email-ids
+ if (thread_id.startsWith("#")) {
+ thread_id = thread_id.substring(1);
+ }
+
+ return thread_id;
+ };
+
+ api.helper.get.email_source_pre = function(identifier) {
+ if(!identifier && api.check.is_inside_email()) {
+ identifier = api.get.email_id();
+ }
+
+ // if we have an old-style ID, construct URL based on that
+ if (api.check.data.is_legacy_email_id(identifier)) {
+ return window.location.origin + window.location.pathname + "?view=att&th=" + identifier + "&attid=0&disp=comp&safe=1&zw";
}
- return window.location.origin + window.location.pathname + "?view=att&th=" + email_id + "&attid=0&disp=comp&safe=1&zw";
+ // otherwise default to new-style ID interface
+ const email_id = api.helper.get.new_email_id(identifier);
+ if(email_id) {
+ return window.location.origin + window.location.pathname + "?view=att&permmsgid=" + email_id + "&attid=0&disp=comp&safe=1&zw";
+ } else {
+ return null;
+ }
};
- api.get.email_source = function(email_id) {
- console.warn("Gmail.js: This function has been deprecated and will be removed in an upcoming release! Please migrate to email_source_async!");
- var url = api.helper.get.email_source_pre(email_id);
+ api.get.email_source = function(identifier) {
+ console.warn("Gmail.js: This function has been deprecated and will be removed in an upcoming release! Please migrate to email_source_async or email_source_promise!");
+ var url = api.helper.get.email_source_pre(identifier);
if (url !== null) {
return api.tools.make_request(url, "GET", true);
}
@@ -2637,14 +3448,14 @@ var Gmail = function(localJQuery) {
};
- api.get.email_source_async = function(email_id, callback, error_callback, preferBinary) {
- api.get.email_source_promise(email_id, preferBinary)
+ api.get.email_source_async = function(identifier, callback, error_callback, preferBinary) {
+ api.get.email_source_promise(identifier, preferBinary)
.then(callback)
.catch(error_callback);
};
- api.get.email_source_promise = function(email_id, preferBinary) {
- const url = api.helper.get.email_source_pre(email_id);
+ api.get.email_source_promise = function(identifier, preferBinary) {
+ const url = api.helper.get.email_source_pre(identifier);
if (url !== null) {
return api.tools.make_request_download_promise(url, preferBinary);
} else {
@@ -2741,8 +3552,8 @@ var Gmail = function(localJQuery) {
api.check.is_conversation_view = function() {
if( api.check.is_new_data_layer() ) {
var conversation_flag = undefined;
- conversation_flag = api.tracker.globals[69];
- return conversation_flag === 1 || conversation_flag === undefined;
+ conversation_flag = api.tracker.globals[24].indexOf(7164);
+ return conversation_flag !== -1;
} else { //To handle classic gmail UI
var flag_name = "bx_vmb";
var flag_value = undefined;
@@ -2791,6 +3602,18 @@ var Gmail = function(localJQuery) {
};
break;
+ case "no":
+ dictionary = {
+ "inbox": "Innboks",
+ "drafts": "Utkast",
+ "spam": "Søppelpost",
+ "forums": "Forumer",
+ "updates": "Oppdateringer",
+ "promotions": "Reklame",
+ "social_updates": "Sosialt"
+ };
+ break;
+
case "nl":
dictionary = {
"inbox": "Postvak IN",
@@ -2837,7 +3660,7 @@ var Gmail = function(localJQuery) {
container.attr("class","G-Ni J-J5-Ji");
var button = $(document.createElement("div"));
- var buttonClasses = "T-I J-J5-Ji ";
+ var buttonClasses = "T-I J-J5-Ji gmailjs ";
if(styleClass !== undefined &&
styleClass !== null &&
styleClass !== ""){
@@ -2874,9 +3697,13 @@ var Gmail = function(localJQuery) {
return create_generic_toolbar_button(content_html, onClickFunction, basicRightStyle, defaultRightStyle, styleClass, api.dom.right_toolbar());
};
- api.tools.add_compose_button = function(composeWindow, content_html, onClickFunction, styleClass) {
+ api.tools.add_compose_button = function(composeWindow, content_html, onClickFunction, styleClass) {
+ var div = $(document.createElement("div"));
+ div.attr("class", "gU Up");
+ div.attr("style", "cursor: pointer !important; transform: translateY(1px);");
+
var button = $(document.createElement("div"));
- var buttonClasses = "T-I J-J5-Ji aoO T-I-atl L3 gmailjscomposebutton ";
+ var buttonClasses = "T-I J-J5-Ji aoO T-I-atl L3 gmailjs gmailjscomposebutton ";
if(styleClass !== undefined){
buttonClasses += styleClass;
}
@@ -2885,7 +3712,46 @@ var Gmail = function(localJQuery) {
button.html(content_html);
button.click(onClickFunction);
- composeWindow.find(".gU.Up > .J-J5-Ji").append(button);
+ div.append(button);
+
+ var sendButton = composeWindow.find(".gU.Up").last();
+ div.insertAfter(sendButton);
+
+ return button;
+ };
+
+ api.tools.add_more_send_option = function(composeWindow, buttonText, onClickFunction, styleClass, imgClass) {
+ var div = $(document.createElement("div"));
+ div.attr("class", "J-N yr");
+ div.attr("style", "user-select: none;");
+ div.attr("role", "menuitem");
+
+ var button = $(document.createElement("div"));
+ var buttonClasses = "J-N-Jz ";
+ if (styleClass !== undefined) {
+ buttonClasses += styleClass;
+ }
+ button.attr("class", buttonClasses);
+ button.attr("style", "user-select: none;");
+
+ var img = $(document.createElement("img"));
+ var imgClassFull = "J-N-JX";
+ if (imgClass !== undefined){
+ imgClassFull = imgClass + " " + imgClassFull;
+ }
+ img.attr("class", imgClassFull);
+ img.attr("style", "user-select: none;");
+ img.attr("role", "menuitem");
+ img.attr("src", "images/cleardot.gif");
+ button.append(img);
+
+ button.append(buttonText);
+ button.click(onClickFunction);
+
+ div.append(button);
+
+ var scheduledSend = composeWindow.find(".J-N.yr").last();
+ div.insertAfter(scheduledSend);
return button;
};
@@ -2934,11 +3800,14 @@ var Gmail = function(localJQuery) {
$("#gmailJsModalWindow").remove();
};
- api.tools.add_modal_window = function(title, content_html, onClickOk, onClickCancel, onClickClose) {
+ api.tools.add_modal_window = function(title, content_html, onClickOk, onClickCancel, onClickClose, okText, cancelText) {
// By default, clicking on cancel or close should clean up the modal window
onClickClose = onClickClose || api.tools.remove_modal_window;
onClickCancel = onClickCancel || api.tools.remove_modal_window;
+ okText = okText || "OK";
+ cancelText = cancelText || "Cancel";
+
var background = $(document.createElement("div"));
background.attr("id","gmailJsModalBackground");
background.attr("class","Kj-JD-Jh");
@@ -2989,13 +3858,13 @@ var Gmail = function(localJQuery) {
okButton.attr("id", "gmailJsModalWindowOk");
okButton.attr("class", "J-at1-auR J-at1-atl");
okButton.attr("name", "ok");
- okButton.text("OK");
+ okButton.text(okText);
okButton.click(onClickOk);
var cancelButton = $(document.createElement("button"));
cancelButton.attr("id", "gmailJsModalWindowCancel");
cancelButton.attr("name", "cancel");
- cancelButton.text("Cancel");
+ cancelButton.text(cancelText);
cancelButton.click(onClickCancel);
controls.append(okButton);
@@ -3026,7 +3895,7 @@ var Gmail = function(localJQuery) {
var minimizeButton = $("[alt='Minimize']")[0];
if(minimizeButton) {
- api.helper.trigger_mouse_click(minimizeButton);
+ minimizeButton.click();
return true;
}
@@ -3066,6 +3935,42 @@ var Gmail = function(localJQuery) {
return undefined;
};
+ /**
+ * Returns data about the currently visible messages available in the DOM:
+ * {
+ * from: {
+ * name: string,
+ * email: string,
+ * },
+ * summary: string, // subject and email summary
+ * thread_id: string,
+ * legacy_email_id: string,
+ * $el: HTMLElement,
+ * }
+ */
+ api.dom.visible_messages = function() {
+ const ret = [];
+ // [draggable="true"] is not always on the rows for some unknown reason
+ $('tbody>tr.zA[role="row"]:visible', api.dom.inbox_content())
+ .each((index, msgEle) => {
+ const nameAndEmail = $('*[email][name]', msgEle);
+ const linkAndSubject = $('*[role=link]', msgEle);
+ // example value: #thread-f:1638756560099919527|msg-f:1638756560099919527"
+ const idNode = msgEle.querySelector("span[data-thread-id]");
+ ret.push({
+ from: {
+ name: nameAndEmail.attr('name'),
+ email: nameAndEmail.attr('email'),
+ },
+ summary: linkAndSubject[0].innerText,
+ thread_id: api.helper.clean_thread_id(idNode && idNode.dataset && idNode.dataset.threadId || ""),
+ legacy_email_id: (idNode && idNode.dataset && idNode.dataset.legacyMessageId || ""),
+ $el: $(msgEle),
+ });
+ });
+ return ret;
+ };
+
// retrieve queue of compose window dom objects
// latest compose at the start of the queue (index 0)
api.dom.composes = function() {
@@ -3076,6 +3981,27 @@ var Gmail = function(localJQuery) {
return objs;
};
+ api.dom.helper = {
+ };
+ /**
+ * triggers a keyboard event inside a textarea, to ensure Gmail updates
+ * the underlying data-model to use the email injected into the textarea.
+ */
+ api.dom.helper.trigger_address = function($el) {
+ // actual DOM element, no jQuery.
+ let el = $el[0];
+ let event = new KeyboardEvent("keydown", {
+ bubbles : true,
+ cancelable : true,
+ key : "Tab",
+ shiftKey : true,
+ keyCode : 9
+ });
+
+ el.focus();
+ el.dispatchEvent(event);
+ };
+
/**
A compose object. Represents a compose window in the DOM and provides a bunch of methods and properties to access & interact with the window
Expects a jQuery DOM element for the compose div
@@ -3113,11 +4039,31 @@ var Gmail = function(localJQuery) {
}
},
+ /**
+ Retrieve the draft thread id
+ */
+ thread_id: function() {
+ let thread_id = this.dom("thread").val() || "";
+
+ return api.helper.clean_thread_id(thread_id);
+ },
+
/**
Is this compose instance inline (as with reply & forwards) or a popup (as with a new compose)
*/
is_inline: function() {
- return this.$el.closest("td.Bu").length > 0;
+ return this.$el.closest(".AO").length > 0;
+ },
+
+ /**
+ Compose type - reply / forward / compose (new)
+ */
+ type: function() {
+ return this.is_inline()
+ ? this.find("input[name=subject]").val().indexOf("Fw") === 0
+ ? "forward"
+ : "reply"
+ : "compose";
},
/**
@@ -3127,41 +4073,80 @@ var Gmail = function(localJQuery) {
options.flat boolean if true will just return an array of all recipients instead of splitting out into to, cc, and bcc
*/
recipients: function(options) {
- if( typeof options !== "object" ) options = {};
- var name_selector = options.type ? "[name=" + options.type + "]" : "";
-
- // determine an array of all emails specified for To, CC and BCC and extract addresses into an object for the callback
- var recipients = options.flat ? [] : {};
- this.$el.find(".GS input[type=hidden]"+name_selector).each(function(idx, recipient ){
- if(options.flat) {
- recipients.push(recipient.value);
+ if (typeof options !== "object") options = {};
+ const peopleKit = api.check.is_peoplekit_compose(this.$el);
+
+ const type_selector = options.type ? "[name=" + options.type + "]" : "";
+
+ const found = peopleKit ?
+ this.$el.find("tr.bzf " + (type_selector || "div[name]") + " div[data-hovercard-id]").map((_, el) => ({
+ type: options.type || el.closest("div[name]").getAttribute("name"),
+ email: el.getAttribute("data-hovercard-id")
+ })) :
+ this.$el.find(".GS input[type=hidden]" + type_selector).map((_, el) => ({
+ type: el.name,
+ email: el.value
+ }));
+
+ if (options.flat) {
+ return found.toArray().map(r => r.email);
+ } else {
+ let result = { to: [], cc: [], bcc: [] };
+ if (options.type) {
+ result[options.type] = found.toArray()
+ .filter(r => r.type === options.type)
+ .map(r => r.email);
} else {
- if(!recipients[recipient.name]) recipients[recipient.name] = [];
- recipients[recipient.name].push(recipient.value);
+ ["to", "cc", "bcc"].forEach(type => {
+ result[type] = found.toArray()
+ .filter(r => r.type === type)
+ .map(r => r.email);
+ });
}
- });
- return recipients;
+ return result;
+ }
},
/**
- Retrieve the current "to" recipients
+ Retrieve the typing area for "to" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
to: function(to) {
- return this.dom("to").val(to);
+ const $el = this.dom("to").val(to);
+ api.dom.helper.trigger_address($el);
+ return $el;
},
/**
- Retrieve the current "cc" recipients
+ Retrieve the typing area for "cc" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
cc: function(cc) {
- return this.dom("cc").val(cc);
+ // ensure cc is visible before setting!
+ if (cc) {
+ const showCc = this.dom("show_cc");
+ showCc.click();
+ }
+
+ const $el = this.dom("cc").val(cc);
+ api.dom.helper.trigger_address($el);
+ return $el;
},
/**
- Retrieve the current "bcc" recipients
+ Retrieve the typing area for "bcc" recipients, not recipients.
+ Either textarea or input, which can be empty if last recipient are typed and selected (by pressing ENTER)
*/
bcc: function(bcc) {
- return this.dom("bcc").val(bcc);
+ // ensure bcc is visible before setting!
+ if (bcc) {
+ const showBcc = this.dom("show_bcc");
+ showBcc.click();
+ }
+
+ const $el = this.dom("bcc").val(bcc);
+ api.dom.helper.trigger_address($el);
+ return $el;
},
/**
@@ -3199,6 +4184,33 @@ var Gmail = function(localJQuery) {
return el.html();
},
+ /**
+ Get the email attachments
+ */
+ attachments: function() {
+ var out = [];
+ var failed = false;
+
+ this.dom("attachments").each(function() {
+ var el = $(this);
+
+ var result = {};
+ result.$el = el;
+ result.name = el.find("div.vI").html();
+ result.size = el.find("div.vJ").html();
+ result.url = el.find("a.dO").attr("href");
+ result.type = "https";
+
+ out.push(result);
+ });
+
+ if (failed) {
+ return undefined;
+ } else {
+ return out;
+ }
+ },
+
/**
Triggers the same action as clicking the "send" button would do.
*/
@@ -3213,6 +4225,20 @@ var Gmail = function(localJQuery) {
return this.$el.find(selector);
},
+ /**
+ Close compose window
+ */
+ close: function() {
+ const e = document.createEvent('Events');
+ e.initEvent('keydown', true, true);
+ e.which = 27;
+ e.keyCode = 27;
+
+ var $body = this.dom('body');
+ $body.focus();
+ $body[0].dispatchEvent(e);
+ },
+
/**
Retrieve preconfigured dom elements for this compose window
*/
@@ -3224,15 +4250,29 @@ var Gmail = function(localJQuery) {
bcc:"textarea[name=bcc]",
id: "input[name=composeid]",
draft: "input[name=draft]",
+ thread: "input[name=rt]",
subject: "input[name=subject]",
subjectbox: "input[name=subjectbox]",
all_subjects: "input[name=subjectbox], input[name=subject]",
- body: "div[contenteditable=true]",
+ body: "div[contenteditable=true]:not([id=subject])",
+ quoted_reply: "input[name=uet]",
reply: "M9",
forward: "M9",
from: "input[name=from]",
- send_button: "div.T-I.T-I-atl:not(.gmailjscomposebutton)"
+ attachments: "div.dL",
+ send_button: "div.T-I.T-I-atl:not(.gmailjscomposebutton)",
+ show_cc: "span.aB.gQ.pE",
+ show_bcc: "span.aB.gQ.pB"
};
+
+ if (api.check.is_peoplekit_compose(this.$el)) {
+ config = Object.assign(config, {
+ to: "div[name=to] input",
+ cc: "div[name=cc] input",
+ bcc: "div[name=bcc] input"
+ });
+ }
+
if(!config[lookup]) api.tools.error("Dom lookup failed. Unable to find config for \"" + lookup + "\"",config,lookup,config[lookup]);
return this.$el.find(config[lookup]);
}
@@ -3250,20 +4290,24 @@ var Gmail = function(localJQuery) {
return new api.dom.email(element);
}
- if (typeof element === "string") {
+ if (typeof element === "string" && api.check.data.is_legacy_email_id(element)) {
this.id = element;
- element = $("div.adn[data-legacy-message-id='" + this.id + "']");
- } else {
- element = $(element);
- }
-
- if (!element || (!element.hasClass("adn"))) api.tools.error("api.dom.email called with invalid element/id");
-
- this.$el = element;
- if (!this.id) {
+ this.$el = $("div.adn[data-legacy-message-id='" + this.id + "']");
+ } else if (typeof element === "string" && api.check.data.is_email_id(element)) {
+ const elem = document.querySelector("div.adn[data-message-id='" + element.replace("msg-f:", "\\#msg-f\\:") + "']");
+ this.id = elem.dataset.legacyMessageId;
+ this.$el = $(elem);
+ } else if (element &&
+ ((element.classList && element.classList.contains("adn")) // DOM
+ || (element.hasClass && element.hasClass("adn")))) // jQuery
+ {
+ this.$el = $(element);
this.id = this.$el.data("legacyMessageId");
+ } else {
+ api.tools.error("api.dom.email called with invalid element/id");
}
+ // silence linter!
return this;
};
@@ -3311,19 +4355,19 @@ var Gmail = function(localJQuery) {
*/
to: function(to_array) {
- // if update data has been passeed, loop through & create a new to_wrapper contents
+ // if update data has been passed, loop through & create a new to_wrapper contents
if (to_array) {
- if (!$.isArray(to_array)) {
+ if (!Array.isArray(to_array)) {
to_array = [to_array];
}
var html = [];
- $.each(to_array, function(index, obj) {
+ for (let obj in to_array) {
html.push( $("").attr({
dir: "ltr",
email: obj.email,
name: obj.name
}).addClass("g2").html(obj.name).wrap("").parent().html());
- });
+ }
this.dom("to_wrapper").html("to " + html.join(", "));
}
@@ -3390,9 +4434,9 @@ var Gmail = function(localJQuery) {
// retrieve & cache the data for this whole thread of emails
var data = api.get.email_data(this.id);
- $.each(data.threads, function(email_id, email_data) {
+ for (let [email_id, email_data] of Object.entries(data.threads)) {
api.dom.email_cache[email_id] = email_data;
- });
+ }
}
return api.dom.email_cache[this.id];
},
@@ -3421,7 +4465,7 @@ var Gmail = function(localJQuery) {
attachments: "div.hq.gt div.aQH span.aZo",
// buttons
- reply_button: "div[role=button].aaq",
+ reply_button: "div[role=button].aaq, div[role=button].bsQ",
menu_button: "div[role=button].aap",
details_button: "div[role=button].ajz"
};
@@ -3442,7 +4486,8 @@ var Gmail = function(localJQuery) {
return new api.dom.thread(element);
}
- if (!element || (!element.hasClass("if"))) api.tools.error("api.dom.thread called with invalid element/id");
+ // this should match the sub_selector
+ if (!element || (!element.hasClass("if") && !element.hasClass("iY"))) api.tools.error("api.dom.thread called with invalid element/id");
this.$el = element;
return this;
};
@@ -3472,10 +4517,9 @@ var Gmail = function(localJQuery) {
api.compose.start_compose = function() {
//The compose button
- var composeEl = $(".T-I.J-J5-Ji.T-I-KE.L3")[0];
-
+ var composeEl = document.getElementsByClassName("T-I T-I-KE L3")[0];
if(composeEl) {
- api.helper.trigger_mouse_click(composeEl);
+ composeEl.click();
return true;
}
@@ -3498,21 +4542,22 @@ var Gmail = function(localJQuery) {
api.new.get = {};
/**
- * Returns the new-style email_id of the latest email visible in the DOM.
+ * Returns the new-style email_id of the latest email visible in the DOM,
+ * or for the provided email-node if provided.
+ *
+ * @param emailElem: Node to extract email-id from. Optional.
*/
- api.new.get.email_id = function() {
- const emailElems = document.querySelectorAll(".adn[data-message-id]");
- if (!emailElems || emailElems.length === 0) {
- return null;
+ api.new.get.email_id = function(emailElem) {
+ // ensure we have an email-element to work with
+ if (!emailElem) {
+ const emailElems = document.querySelectorAll(".adn[data-message-id]");
+ if (!emailElems || emailElems.length === 0) {
+ return null;
+ }
+ emailElem = emailElems[emailElems.length - 1];
}
- const emailElem = emailElems[emailElems.length - 1];
- let declaredId = emailElem.dataset["messageId"];
- if (declaredId && declaredId.startsWith("#")) {
- return declaredId.substring(1);
- } else {
- return declaredId;
- }
+ return api.helper.get.new_email_id(emailElem);
};
/**
@@ -3532,9 +4577,15 @@ var Gmail = function(localJQuery) {
*
* @param email_id: new style email id. Legacy IDs not supported. If empty, default to latest in view.
*/
- api.new.get.email_data = function(email_id) {
- email_id = email_id || api.new.get.email_id();
- return api.cache.emailIdCache[email_id];
+ api.new.get.email_data = function(identifier) {
+ identifier = identifier || api.new.get.email_id();
+ const email_id = api.helper.get.new_email_id(identifier);
+
+ if (!email_id) {
+ return null;
+ } else {
+ return api.cache.emailIdCache[email_id];
+ }
};
/**
@@ -3542,15 +4593,29 @@ var Gmail = function(localJQuery) {
*
* @param thread_id: new style thread id. Legacy IDs not supported. If empty, default to current.
*/
- api.new.get.thread_data = function(thread_id) {
- thread_id = thread_id || api.new.get.thread_id();
- return api.cache.threadCache[thread_id];
+ api.new.get.thread_data = function(identifier) {
+ identifier = identifier || api.new.get.thread_id();
+ const thread_id = api.helper.get.thread_id(identifier);
+
+ if (!thread_id) {
+ return null;
+ } else {
+ return api.cache.threadCache[thread_id];
+ }
};
// setup XHR interception as early as possible, to ensure we get all relevant email-data!
if (typeof(document) !== "undefined") {
api.tools.xhr_watcher();
}
+
+ // set up embedded data watcher as early as possible, to ensure we get all relevant email-data!
+ // do not wait for document load event, embedded data are loaded before...
+ // content-script must be configured with "run_at": "document_start" to be able to watch embedded data
+ if (typeof(document) !== "undefined") {
+ api.tools.embedded_data_watcher();
+ }
+
return api;
};
diff --git a/test/test.locale.js b/test/test.locale.js
index bb2b6468..7641b43a 100644
--- a/test/test.locale.js
+++ b/test/test.locale.js
@@ -1,7 +1,7 @@
"use strict";
let assert = require('assert');
let Gmail = require('../src/gmail').Gmail;
-let gmail = new Gmail();
+let gmail = new Gmail(false);
describe("Locale-parsing", () => {
it("Recognizes consistently cased locales", () => {
diff --git a/test/test.new.js b/test/test.new.js
new file mode 100644
index 00000000..4fc44150
--- /dev/null
+++ b/test/test.new.js
@@ -0,0 +1,140 @@
+"use strict";
+let assert = require('assert');
+let Gmail = require('../src/gmail').Gmail;
+let gmail = new Gmail(false);
+
+// prep cache for tests
+const validEmailLegacyId = "16a0d1f820d515e2";
+const validEmailNewId = "msg-a:12345";
+const invalidEmailLegacyid = "16a0d1f820d515e3";
+const invalidEmailNewId = "msg-a:12346";
+const email = { foo: "bar" };
+email.id = validEmailNewId;
+email.legacy_email_id = validEmailLegacyId;
+
+gmail.cache.emailIdCache[validEmailNewId] = email;
+gmail.cache.emailLegacyIdCache[validEmailLegacyId] = email;
+
+let thread = { bar: "foo" };
+let validThreadId = "thread-a:12345";
+gmail.cache.threadCache[validThreadId] = thread;
+
+
+describe("gmail.new.get", () => {
+ const elem = {
+ dataset: {
+ "messageId": validEmailNewId
+ }
+ };
+
+ it("email_id() can look up based on HTML elements", () => {
+ let id = gmail.new.get.email_id(elem);
+ assert.equal(id, validEmailNewId);
+ });
+
+ it("email_id() can look up based on DomEmail instance", () => {
+ let domEmail = {
+ $el: [elem]
+ };
+ let id = gmail.new.get.email_id(domEmail);
+ assert.equal(id, validEmailNewId);
+ });
+
+ it("email_data() can look up based on legacy-style IDs, with warning", () => {
+ let res = gmail.new.get.email_data(validEmailLegacyId);
+ assert.equal(res, email);
+ });
+
+ it("email_data() returns null when looking up invalid legacy-style IDs", () => {
+ let res = gmail.new.get.email_data(invalidEmailLegacyid);
+ assert.equal(res, null);
+ });
+
+ it("email_data() creates warning when looking up legacy-style IDs", () => {
+ let warnInvoked = false;
+ let origWarnFunc = console.warn;
+ console.warn = () => {
+ warnInvoked = true;
+ };
+
+ let res = gmail.new.get.email_data(validEmailLegacyId);
+
+ console.warn = origWarnFunc;
+ assert.equal(true, warnInvoked);
+ });
+
+ it("email_data() can look up based on new-style IDs", () => {
+ let res = gmail.new.get.email_data(validEmailNewId);
+ assert.equal(res, email);
+ });
+
+ it("email_data() returns null when looking up invalid new-style IDs", () => {
+ let res = gmail.new.get.email_data(invalidEmailNewId);
+ assert.equal(res, null);
+ });
+
+ it("email_data() returns looks up current email_id when provided null-value", () => {
+ let origFunc = gmail.new.get.email_id;
+
+ gmail.new.get.email_id = () => { return validEmailNewId; };
+
+ let res = gmail.new.get.email_data();
+ assert.equal(res, email);
+
+ gmail.new.get.email_id = origFunc;
+ });
+
+ it("email_data() returns null without warning when email_id not resolved", () => {
+ let warnInvoked = false;
+ let origWarnFunc = console.warn;
+ console.warn = () => {
+ warnInvoked = true;
+ };
+
+ let origIdFunc = gmail.new.get.email_id;
+ gmail.new.get.email_id = () => { return null; };
+
+ let res = gmail.new.get.email_data();
+
+ gmail.new.get.email_id = origIdFunc;
+ console.warn = origWarnFunc;
+
+ assert.equal(false, warnInvoked);
+ assert.equal(null, res);
+ });
+
+ it("thread_data() resolves thread", () => {
+ let res = gmail.new.get.thread_data(validThreadId);
+ assert.equal(res, thread);
+ });
+
+ it("thread_data() looks up current thread_id when provided null-value", () => {
+ let origFunc = gmail.new.get.thread_id;
+
+ gmail.new.get.thread_id = () => { return validThreadId; };
+
+ let res = gmail.new.get.thread_data();
+ assert.equal(res, thread);
+
+ gmail.new.get.thread_id = origFunc;
+ });
+
+ it("thread_data() returns null without warning when thread_id not resolved", () => {
+ let warnInvoked = false;
+ let origWarnFunc = console.warn;
+ console.warn = () => {
+ warnInvoked = true;
+ };
+
+ let origIdFunc = gmail.new.get.thread_id;
+ gmail.new.get.thread_id = () => { return null; };
+
+ let res = gmail.new.get.thread_data();
+
+ gmail.new.get.thread_id = origIdFunc;
+ console.warn = origWarnFunc;
+
+ assert.equal(false, warnInvoked);
+ assert.equal(null, res);
+ });
+});
diff --git a/test/test.parsing.js b/test/test.parsing.js
index 267acddc..815fcb69 100644
--- a/test/test.parsing.js
+++ b/test/test.parsing.js
@@ -3,473 +3,1202 @@
let assert = require("assert");
let Gmail = require("../src/gmail").Gmail;
-let testData = require("./testdata-parser.js");
-
-describe("Response-parsing", () => {
-
- it("Handles JSON-responses consistently", () => {
- var gmail = new Gmail();
- var parsed = gmail.tools.parse_response(testData.parse_response_json_data);
-
- assert.equal(2, parsed.length);
- assert.equal(8, parsed[0].length);
- assert.equal(8, parsed[1].length);
- });
-
- it("Handles visible_emails_post consistently", () => {
- var gmail = new Gmail();
- var emails = gmail.helper.get.visible_emails_post(testData.visible_emails_post_data);
-
- assert.equal(17, emails.length);
- assert.equal("Selfie", emails[0].title);
- });
-
- it("Handles email_data_post consistently", () => {
- var gmail = new Gmail();
- var email = gmail.helper.get.email_data_post(testData.email_data_post_data);
-
- assert.equal("156559dc1867409f", email.first_email);
- assert.equal("156559dc1867409f", email.thread_id);
- assert.equal("Ny pålogging fra Chrome på Windows", email.subject);
- assert.equal(2, email.people_involved.length);
- assert.equal(1, email.total_emails);
- });
-});
-
-describe("Attachment-parsing", () => {
-
- var email_attachment_url_png = "";
- var email_attachment_url_pdf = "";
-
- it("Handles attachments URLs consistently", () => {
- var gmail = new Gmail();
-
- var testCases = [
- {
- value: "image/png:typescript.png:https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.1&disp=safe&zw",
- type: "image/png",
- url: "https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.1&disp=safe&zw"
- },
- {
- value: "application/pdf:image2016-11-15-132610.pdf:https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.3&disp=safe&zw",
- type: "application/pdf",
- url: "https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.3&disp=safe&zw"
- }
- ];
-
- for (var i=0; i < testCases.length; i++) {
- var testCase = testCases[i];
-
- var result = gmail.tools.parse_attachment_url(http://github.com/testCase.value);
- assert.equal(result.type, testCase.type);
- assert.equal(result.url, testCase.url);
- }
- });
-
-});
-
-describe("Current-page parsing", () => {
- it("detects known pages", () => {
- const gmail = new Gmail();
- const testCases = {
- "inbox": "inbox",
- "inbox/14c313949290f26d": "email",
- "inbox/14c313949290f26d?compose=new": "email",
- "inbox/14c313949290f26d?compose=24c313949290f26d": "email",
- "inbox/p2": "inbox",
- "starred": "starred",
- "sent": "sent",
- "sent/14c313949290f26d": "email",
- "sent/p2": "sent",
- "drafts": "drafts",
- "search/test": "search/test",
- "category/social": "category/social",
- "category/social/p2": "category/social",
- "label/bank": "label/bank",
- "label/bank/p2": "label/bank"
- };
-
- for (let testCaseValue in testCases) {
- let expected = testCases[testCaseValue];
-
- let result = gmail.get.current_page(testCaseValue);
- assert.equal(result, expected);
- }
- });
-});
-
-describe("Name-parsing", () => {
-
- const gmail = new Gmail();
- const testName = function(source) {
- const result = gmail.tools.extract_name(source + " <>");
- assert.deepEqual(result, source);
- };
-
- it("handles no spaces in name", () => {
- testName("Burt");
- });
-
- it("handles spaces in name", () => {
- testName("Curt Cobain");
- });
-
- it("handles vikings", () => {
- testName("Jostein Kjønigsen");
- });
-
- it("handles zeh germans", () => {
- testName("Frunk Münster");
- });
-
- it("handles le frenchies", () => {
- testName("Madamoselle Emálie");
- });
-
- it("handles mexicans", () => {
- testName("Senõr Alapenõ on a stick");
- });
-});
-
-describe("List-prefix checking", () => {
- const gmail = new Gmail();
-
- const testCase = function(list, searchee, expected) {
- const result = gmail.helper.array_starts_with(list, searchee);
- assert.equal(expected, result);
- };
-
- it("returns false for null or empty list", () => {
- testCase(null, "key", false);
- testCase([], "key", false);
- });
-
- it("returns false for miss", () => {
- testCase(["ui", "yes"], "uiv", false);
- });
-
- it("returns true for exact hit", () => {
- testCase(["ui", "yes"], "ui", true);
- });
-});
-
-describe("Sub-list extraction", () => {
- const gmail = new Gmail();
-
- const testCase = function(listlist, prefix, expected) {
- const result = gmail.helper.get.array_sublist(listlist, prefix);
- assert.deepEqual(expected, result);
- };
-
- it("returns null for null or empty list", () => {
- testCase(null, "ui", null);
- testCase([], "ui", null);
- });
-
- it("returns null for no match", () => {
- testCase([["uiv", "a"]], "ui", null);
- });
-
- it("returns the full matching list on match", () => {
- testCase([
- ["a", "b", "c"],
- ["ui", "yeah"],
- ["d", "e", "f"]
- ], "ui", ["ui", "yeah"]);
- });
-});
-
-describe("New Gmail data-format", () => {
- const gmail = new Gmail();
-
- it("Detects thread-id", () => {
- assert.ok(gmail.check.data.is_thread_id("thread-a:r266633262821436756"));
- assert.ok(!gmail.check.data.is_thread_id("^smartlabel_notification"));
- assert.ok(!gmail.check.data.is_thread_id("something with thread-a:r266633262821436756"));
- assert.ok(!gmail.check.data.is_thread_id("msg-a:r6431891629648253702"));
- });
-
- it("Detects thread-objects", () => {
- assert.ok(gmail.check.data.is_thread({
- "1": "thread-a:r266633262821436756"
- }));
- assert.ok(!gmail.check.data.is_thread({
- "1": "msg-a:r6431891629648253702"
- }));
-
- assert.ok(!gmail.check.data.is_thread(null));
- assert.ok(!gmail.check.data.is_thread({}));
- assert.ok(!gmail.check.data.is_thread({
- "1": "string"
- }));
- assert.ok(!gmail.check.data.is_thread({
- "1": [
- "thread-a:r266633262821436756"
- ]
- }));
- });
-
- it("Detects email-id", () => {
- assert.ok(gmail.check.data.is_email_id("msg-a:r6431891629648253702"));
- assert.ok(!gmail.check.data.is_email_id("^smartlabel_notification"));
- assert.ok(!gmail.check.data.is_email_id("something with msg-a:r64318916296482537026"));
- assert.ok(!gmail.check.data.is_email_id("thread-a:r266633262821436756"));
- });
-
- it("Detects email-objects", () => {
- assert.ok(gmail.check.data.is_email({
- "1": "msg-a:r6431891629648253702"
- }));
- assert.ok(gmail.check.data.is_email({
- "1": "msg-f:6431891629648253702"
- }));
- assert.ok(!gmail.check.data.is_email({
- "1": "thread-a:r266633262821436756"
- }));
- assert.ok(!gmail.check.data.is_email({
- "1": "msg-a:bump-r266633262821436756"
- }));
-
- assert.ok(!gmail.check.data.is_email(null));
- assert.ok(!gmail.check.data.is_email({}));
- assert.ok(!gmail.check.data.is_email({
- "1": "string"
- }));
- assert.ok(!gmail.check.data.is_email({
- "1": [
- "msg-a:r6431891629648253702"
- ]
- }));
- assert.ok(!gmail.check.data.is_email({
- "1": [
- "msg-a:bump-r6431891629648253702"
- ]
- }));
- });
-
- it("Detects smart-label arrays", () => {
- const testee = gmail.check.data.is_smartlabels_array;
- assert.ok(testee(["^a", "^pfg", "^woo"]));
- assert.ok(!testee(["a", "pfg", "woo"]));
- assert.ok(!testee([1, 2, 3, 4]));
- });
-
- it ("Detects JSON-strings", () => {
- const testee = gmail.check.data.is_json_string;
- assert.ok(testee("{\"a\": 1}"));
- assert.ok(testee("[1, 2, 3]"));
-
- assert.ok(!testee("{abc"));
- assert.ok(!testee("[1, 2, 3"));
- assert.ok(!testee("{1, 2, 3"));
- assert.ok(!testee("[1, 2, 3}"));
- assert.ok(!testee("{1, 2, 3]"));
-
- assert.ok(testee("{\"a\": 1}\n"));
- assert.ok(testee("[1, 2, 3]\n"));
- });
-});
-
-describe("Graph-traversal", () => {
- const gmail = new Gmail();
- const testee = gmail.tools.extract_from_graph;
-
- it("Does not crash on null-object", () => {
- testee(null, () => true);
- });
-
- it("Does not crash on empty object", () => {
- testee({}, () => true);
- });
-
- it("Crashes on null-predicate.", () => {
- try {
- testee({}, null);
- testee({a: "a"}, null);
- testee({}, undefined);
- testee({a: "a"}, undefined);
- assert.fail("Should have failed!");
- } catch(err) {
- assert.ok(true);
- }
- });
-
- it("Can extract from root-node based on criteria", () => {
- let result = testee({
- "1": "identifier"
- }, (item) => { return item["1"] === "identifier";});
- assert.equal(1, result.length);
- });
-
- it("Can extract from direct child-node(s) based on criteria", () => {
- const testObj = {
- child1: {
- "1": "identifier",
- "id": "child1"
- },
- child2: {
- "1": "identifier",
- "id": "child2"
- }
- };
- let result = testee(testObj, (item) => { return item["1"] === "identifier";});
- assert.equal(2, result.length);
-
- assert.equal("child1", result[0].id);
- assert.equal("child2", result[1].id);
- });
-
- it("Can extract from deep child-node(s) based on criteria", () => {
- const testObj = {
- child1: {
- "1": "identifier",
- "id": "child1"
- },
- nested: {
- nesteder: {
- child2: {
- "1": "identifier",
- "id": "child2"
- }
- }
- }
- };
- let result = testee(testObj, (item) => { return item["1"] === "identifier";});
- assert.equal(2, result.length);
-
- assert.equal("child1", result[0].id);
- assert.equal("child2", result[1].id);
- });
-
- it("Can extract from arrays in the graph based on criteria", () => {
- const testObj = {
- nested: {
- nesteder: {
- children: [
- {
- "1": "identifier",
- "id": "child1"
- },
- {
- "1": "identifier",
- "id": "child2"
- }
- ]
- }
- }
- };
- let result = testee(testObj, (item) => { return item["1"] === "identifier";});
- assert.equal(2, result.length);
-
- assert.equal("child1", result[0].id);
- assert.equal("child2", result[1].id);
+// let testData = require("./testdata-parser.js");
+
+// let jsdom = require('jsdom');
+// let jquery = require('jquery')(new jsdom.JSDOM().window);
+
+// describe("Response-parsing", () => {
+
+// it("Handles JSON-responses consistently", () => {
+// var gmail = new Gmail();
+// var parsed = gmail.tools.parse_response(testData.parse_response_json_data);
+
+// assert.equal(2, parsed.length);
+// assert.equal(8, parsed[0].length);
+// assert.equal(8, parsed[1].length);
+// });
+
+// it("Handles visible_emails_post consistently", () => {
+// var gmail = new Gmail();
+// var emails = gmail.helper.get.visible_emails_post(testData.visible_emails_post_data);
+
+// assert.equal(17, emails.length);
+// assert.equal("Selfie", emails[0].title);
+// });
+
+// it("Handles email_data_post consistently", () => {
+// var gmail = new Gmail();
+// var email = gmail.helper.get.email_data_post(testData.email_data_post_data);
+
+// assert.equal("156559dc1867409f", email.first_email);
+// assert.equal("156559dc1867409f", email.thread_id);
+// assert.equal("Ny pålogging fra Chrome på Windows", email.subject);
+// assert.equal(2, email.people_involved.length);
+// assert.equal(1, email.total_emails);
+// });
+// });
+
+// describe("Attachment-parsing", () => {
+
+// var email_attachment_url_png = "";
+// var email_attachment_url_pdf = "";
+
+// it("Handles attachments URLs consistently", () => {
+// var gmail = new Gmail();
+
+// var testCases = [
+// {
+// value: "image/png:typescript.png:https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.1&disp=safe&zw",
+// type: "image/png",
+// url: "https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.1&disp=safe&zw"
+// },
+// {
+// value: "application/pdf:image2016-11-15-132610.pdf:https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.3&disp=safe&zw",
+// type: "application/pdf",
+// url: "https://mail.google.com/mail/u/0/?ui=2&ik=4b86ba4469&view=att&th=158de724051f63cf&attid=0.3&disp=safe&zw"
+// }
+// ];
+
+// for (var i=0; i < testCases.length; i++) {
+// var testCase = testCases[i];
+
+// var result = gmail.tools.parse_attachment_url(http://github.com/testCase.value);
+// assert.equal(result.type, testCase.type);
+// assert.equal(result.url, testCase.url);
+// }
+// });
+
+// });
+
+// describe("Sent-mail-parsing", () => {
+// it("Handles sent email JSON consistently", () => {
+// var gmail = new Gmail();
+// var data = JSON.parse(testData.new_gmail_sent_email_json);
+// var parsed = gmail.tools.parse_sent_message_payload(data);
+
+// assert.equal(parsed["1"], "msg-a:r1280593055912233690");
+// assert.equal(parsed.id, "msg-a:r1280593055912233690");
+// assert.equal(parsed.subject, "Test Parse Sent");
+// assert.equal(parsed.timestamp, "1562634059674");
+// assert.equal(parsed.content_html, "Test
Link Test
--
Thanks,
Eric Karlsson
Product Development
+1 240.688.9219
");
+// assert.equal(parsed.ishtml, 1);
+// assert.deepStrictEqual(parsed.date, new Date("2019-07-09T01:00:59.674Z"));
+
+// assert.equal(parsed.from.name, "Eric Karlsson1");
+// assert.equal(parsed.from.address, "eric.karlsson1@gmail.com");
+
+// assert.equal(parsed.to.length, 2);
+// assert.equal(parsed.to[0].name, "Eric Karlsson2");
+// assert.equal(parsed.to[0].address, "eric.karlsson2@gmail.com");
+// assert.equal(parsed.to[1].name, undefined);
+// assert.equal(parsed.to[1].address, "eric.karlsson3@gmail.com");
+
+// assert.equal(parsed.cc.length, 2);
+// assert.equal(parsed.cc[0].name, undefined);
+// assert.equal(parsed.cc[0].address, "eric.karlsson4@gmail.com");
+// assert.equal(parsed.cc[1].name, undefined);
+// assert.equal(parsed.cc[1].address, "eric.karlsson5@gmail.com");
+
+// assert.equal(parsed.bcc.length, 2);
+// assert.equal(parsed.bcc[0].name, "Eric Karlsson6");
+// assert.equal(parsed.bcc[0].address, "eric.karlsson6@gmail.com");
+// assert.equal(parsed.bcc[1].name, "Eric Karlsson7");
+// assert.equal(parsed.bcc[1].address, "eric.karlsson7@gmail.com");
+
+// assert.equal(parsed.attachments.length, 2);
+// assert.equal(parsed.attachments[0].id, "f_jxv3xqgb1");
+// assert.equal(parsed.attachments[0].name, "Socket Error.PNG");
+// assert.equal(parsed.attachments[0].type, "image/png");
+// assert.equal(parsed.attachments[0].url, "https://mail.google.com/mail/?ui=2&ik=5a14ab333d&attid=0.1&permmsgid=msg-a:r1280593055912233690&view=att&realattid=f_jxv3xqgb1&zw");
+// assert.equal(parsed.attachments[0].size, 108256);
+// assert.equal(parsed.attachments[1].id, "f_jxv3xqg00");
+// assert.equal(parsed.attachments[1].name, "8002291_3.jpg");
+// assert.equal(parsed.attachments[1].type, "image/jpeg");
+// assert.equal(parsed.attachments[1].url, "https://mail.google.com/mail/?ui=2&ik=5a14ab333d&attid=0.2&permmsgid=msg-a:r1280593055912233690&view=att&realattid=f_jxv3xqg00&zw");
+// assert.equal(parsed.attachments[1].size, 2312479);
+
+// assert.ok(parsed.email_node);
+// });
+// });
+
+// describe("Current-page parsing", () => {
+// it("detects known pages", () => {
+// const gmail = new Gmail();
+// const testCases = {
+// "inbox": "inbox",
+// "inbox/14c313949290f26d": "email",
+// "inbox/14c313949290f26d?compose=new": "email",
+// "inbox/14c313949290f26d?compose=24c313949290f26d": "email",
+// "inbox/p2": "inbox",
+// "starred": "starred",
+// "sent": "sent",
+// "sent/14c313949290f26d": "email",
+// "sent/p2": "sent",
+// "drafts": "drafts",
+// "search/test": "search/test",
+// "category/social": "category/social",
+// "category/social/p2": "category/social",
+// "label/bank": "label/bank",
+// "label/bank/p2": "label/bank"
+// };
+
+// for (let testCaseValue in testCases) {
+// let expected = testCases[testCaseValue];
+
+// let result = gmail.get.current_page(testCaseValue);
+// assert.equal(result, expected);
+// }
+// });
+// });
+
+// describe("Name-parsing", () => {
+
+// const gmail = new Gmail();
+// const testName = function(source) {
+// const result = gmail.tools.extract_name(source + " <>");
+// assert.deepEqual(result, source);
+// };
+
+// it("handles no spaces in name", () => {
+// testName("Burt");
+// });
+
+// it("handles spaces in name", () => {
+// testName("Curt Cobain");
+// });
+
+// it("handles vikings", () => {
+// testName("Jostein Kjønigsen");
+// });
+
+// it("handles zeh germans", () => {
+// testName("Frunk Münster");
+// });
+
+// it("handles le frenchies", () => {
+// testName("Madamoselle Emálie");
+// });
+
+// it("handles mexicans", () => {
+// testName("Senõr Alapenõ on a stick");
+// });
+// });
+
+// describe("List-prefix checking", () => {
+// const gmail = new Gmail();
+
+// const testCase = function(list, searchee, expected) {
+// const result = gmail.helper.array_starts_with(list, searchee);
+// assert.equal(expected, result);
+// };
+
+// it("returns false for null or empty list", () => {
+// testCase(null, "key", false);
+// testCase([], "key", false);
+// });
+
+// it("returns false for miss", () => {
+// testCase(["ui", "yes"], "uiv", false);
+// });
+
+// it("returns true for exact hit", () => {
+// testCase(["ui", "yes"], "ui", true);
+// });
+// });
+
+// describe("Sub-list extraction", () => {
+// const gmail = new Gmail();
+
+// const testCase = function(listlist, prefix, expected) {
+// const result = gmail.helper.get.array_sublist(listlist, prefix);
+// assert.deepEqual(expected, result);
+// };
+
+// it("returns null for null or empty list", () => {
+// testCase(null, "ui", null);
+// testCase([], "ui", null);
+// });
+
+// it("returns null for no match", () => {
+// testCase([["uiv", "a"]], "ui", null);
+// });
+
+// it("returns the full matching list on match", () => {
+// testCase([
+// ["a", "b", "c"],
+// ["ui", "yeah"],
+// ["d", "e", "f"]
+// ], "ui", ["ui", "yeah"]);
+// });
+// });
+
+// describe("New Gmail data-format", () => {
+// const gmail = new Gmail();
+
+// it("Detects thread-id", () => {
+// assert.ok(gmail.check.data.is_thread_id("thread-a:r266633262821436756"));
+// assert.ok(!gmail.check.data.is_thread_id("^smartlabel_notification"));
+// assert.ok(!gmail.check.data.is_thread_id("something with thread-a:r266633262821436756"));
+// assert.ok(!gmail.check.data.is_thread_id("msg-a:r6431891629648253702"));
+// });
+
+// it("Detects thread-objects", () => {
+// assert.ok(gmail.check.data.is_thread({
+// "1": "thread-a:r266633262821436756"
+// }));
+// assert.ok(!gmail.check.data.is_thread({
+// "1": "msg-a:r6431891629648253702"
+// }));
+
+// assert.ok(!gmail.check.data.is_thread(null));
+// assert.ok(!gmail.check.data.is_thread({}));
+// assert.ok(!gmail.check.data.is_thread({
+// "1": "string"
+// }));
+// assert.ok(!gmail.check.data.is_thread({
+// "1": [
+// "thread-a:r266633262821436756"
+// ]
+// }));
+// });
+
+// it("Detects new-style email-id", () => {
+// assert.ok(gmail.check.data.is_email_id("msg-a:r6431891629648253702"));
+// assert.ok(!gmail.check.data.is_email_id("^smartlabel_notification"));
+// assert.ok(!gmail.check.data.is_email_id("something with msg-a:r64318916296482537026"));
+// assert.ok(!gmail.check.data.is_email_id("thread-a:r266633262821436756"));
+// assert.ok(!gmail.check.data.is_email_id("16a0d1f820d515e3"));
+// });
+
+// it("Detects legacy-style email-id", () => {
+// assert.ok(gmail.check.data.is_legacy_email_id("16a0d1f820d515e3"));
+// assert.ok(!gmail.check.data.is_legacy_email_id("msg-a:r6431891629648253702"));
+// });
+
+// it("Detects email-objects", () => {
+// assert.ok(gmail.check.data.is_email({
+// "1": "msg-a:r6431891629648253702"
+// }));
+// assert.ok(gmail.check.data.is_email({
+// "1": "msg-f:6431891629648253702"
+// }));
+// assert.ok(!gmail.check.data.is_email({
+// "1": "thread-a:r266633262821436756"
+// }));
+// assert.ok(!gmail.check.data.is_email({
+// "1": "msg-a:bump-r266633262821436756"
+// }));
+
+// assert.ok(!gmail.check.data.is_email(null));
+// assert.ok(!gmail.check.data.is_email({}));
+// assert.ok(!gmail.check.data.is_email({
+// "1": "string"
+// }));
+// assert.ok(!gmail.check.data.is_email({
+// "1": [
+// "msg-a:r6431891629648253702"
+// ]
+// }));
+// assert.ok(!gmail.check.data.is_email({
+// "1": [
+// "msg-a:bump-r6431891629648253702"
+// ]
+// }));
+// });
+
+// it("Detects smart-label arrays", () => {
+// const testee = gmail.check.data.is_smartlabels_array;
+// assert.ok(testee(["^a", "^pfg", "^woo"]));
+// assert.ok(!testee(["a", "pfg", "woo"]));
+// assert.ok(!testee([1, 2, 3, 4]));
+// });
+
+// it ("Detects JSON-strings", () => {
+// const testee = gmail.check.data.is_json_string;
+// assert.ok(testee("{\"a\": 1}"));
+// assert.ok(testee("[1, 2, 3]"));
+
+// assert.ok(!testee("{abc"));
+// assert.ok(!testee("[1, 2, 3"));
+// assert.ok(!testee("{1, 2, 3"));
+// assert.ok(!testee("[1, 2, 3}"));
+// assert.ok(!testee("{1, 2, 3]"));
+
+// assert.ok(testee("{\"a\": 1}\n"));
+// assert.ok(testee("[1, 2, 3]\n"));
+// });
+// });
+
+// describe("Graph-traversal", () => {
+// const gmail = new Gmail();
+// const testee = gmail.tools.extract_from_graph;
+
+// it("Does not crash on null-object", () => {
+// testee(null, () => true);
+// });
+
+// it("Does not crash on empty object", () => {
+// testee({}, () => true);
+// });
+
+// it("Crashes on null-predicate.", () => {
+// try {
+// testee({}, null);
+// testee({a: "a"}, null);
+// testee({}, undefined);
+// testee({a: "a"}, undefined);
+// assert.fail("Should have failed!");
+// } catch(err) {
+// assert.ok(true);
+// }
+// });
+
+// it("Can extract from root-node based on criteria", () => {
+// let result = testee({
+// "1": "identifier"
+// }, (item) => { return item["1"] === "identifier";});
+// assert.equal(1, result.length);
+// });
+
+// it("Can extract from direct child-node(s) based on criteria", () => {
+// const testObj = {
+// child1: {
+// "1": "identifier",
+// "id": "child1"
+// },
+// child2: {
+// "1": "identifier",
+// "id": "child2"
+// }
+// };
+// let result = testee(testObj, (item) => { return item["1"] === "identifier";});
+// assert.equal(2, result.length);
+
+// assert.equal("child1", result[0].id);
+// assert.equal("child2", result[1].id);
+// });
+
+// it("Can extract from deep child-node(s) based on criteria", () => {
+// const testObj = {
+// child1: {
+// "1": "identifier",
+// "id": "child1"
+// },
+// nested: {
+// nesteder: {
+// child2: {
+// "1": "identifier",
+// "id": "child2"
+// }
+// }
+// }
+// };
+// let result = testee(testObj, (item) => { return item["1"] === "identifier";});
+// assert.equal(2, result.length);
+
+// assert.equal("child1", result[0].id);
+// assert.equal("child2", result[1].id);
+// });
+
+// it("Can extract from arrays in the graph based on criteria", () => {
+// const testObj = {
+// nested: {
+// nesteder: {
+// children: [
+// {
+// "1": "identifier",
+// "id": "child1"
+// },
+// {
+// "1": "identifier",
+// "id": "child2"
+// }
+// ]
+// }
+// }
+// };
+// let result = testee(testObj, (item) => { return item["1"] === "identifier";});
+// assert.equal(2, result.length);
+
+// assert.equal("child1", result[0].id);
+// assert.equal("child2", result[1].id);
+// });
+
+// it("Masks failure in probing function, when accesing non-existant data", () => {
+// const testObj = {
+// "a": "a"
+// };
+// let result = testee(testObj, (item) => {
+// return item[0]["a"].substring(5) === "z";
+// });
+// assert.equal(0, result.length);
+// });
+
+// it("Can extract arrays when predicate matches", () => {
+// const expected = [1,2,3];
+// const testObj = {
+// "a": expected
+// };
+// let result = testee(testObj, Array.isArray);
+// assert.equal(1, result.length);
+// assert.equal(expected, result[0]);
+// });
+
+// it("Can extract node when root-object is array", () => {
+// const testObj = [ "boo", "abc" ];
+// let result = testee(testObj, (item) => { return item === "abc"; });
+// assert.equal(1, result.length);
+// assert.equal("abc", result[0]);
+// });
+// });
+
+// describe("New Gmail event-triggering", () => {
+// const gmail = new Gmail();
+// const testCase = (data, asserts) => {
+// const events = {};
+// const params = {
+// body_params: JSON.parse(data)
+// };
+// // we must force, because request_payload tries to do URL detection
+// gmail.tools.parse_request_payload(params, events, true);
+// asserts(events);
+// };
+
+// // TODO: refactor these tests into the same form as those below.
+// it("Triggers for send_email", () => {
+// testCase(testData.new_gmail_send_email_data, (events) => {
+// assert.ok(events.send_message);
+// });
+// });
+// it("Triggers for archive", () => {
+// testCase(testData.new_gmail_archive_action_body_params, (events) => {
+// assert.ok(events.archive);
+// });
+// });
+// it("Triggers for new_email", () => {
+// testCase(testData.new_gmail_new_email_body_params, (events) => {
+// assert.ok(events.new_email);
+// });
+// });
+
+// // it("Extracts compose-id", () => {
+
+// // });
+// });
+
+// describe("New Gmail event-parsing", () => {
+// const gmail = new Gmail();
+// const data = JSON.parse(testData.new_gmail_archive_action_body_params);
+// const threads = gmail.tools.extract_from_graph(data, gmail.check.data.is_thread);
+// const threadData = threads.map(thread => gmail.tools.get_thread_data(thread))[0];
+
+// let testXhrEventParsing = function (jsonXhrData, eventName) {
+// const api = new Gmail();
+// const xhrData = JSON.parse(jsonXhrData);
+
+// const threads = api.tools.extract_from_graph(xhrData, api.check.data.is_thread);
+// const actionType = api.tools.check_event_type(threads[0]);
+
+// assert.equal(eventName, actionType);
+// };
+
+// it("parses archived messages", () => {
+// const xhrData = testData.new_gmail_archive_action_body_params;
+// testXhrEventParsing(xhrData, "archive");
+// });
+
+// it("parses deleted messages", () => {
+// const xhrData = testData.new_gmail_delete_action_body_params;
+// testXhrEventParsing(xhrData, "delete");
+// });
+
+// it("parses read messages", () => {
+// const xhrData = testData.new_gmail_read_action_body_params;
+// testXhrEventParsing(xhrData, "read");
+// });
+
+// it("parses unread messages", () => {
+// const xhrData = testData.new_gmail_unread_action_body_params;
+// testXhrEventParsing(xhrData, "unread");
+// });
+
+// it("parses open_email messages", () => {
+// const xhrData = testData.new_gmail_open_email_action_body_params;
+// testXhrEventParsing(xhrData, "open_email");
+// });
+
+// it("parses new_email message", () => {
+// const xhrData = testData.new_gmail_new_email_body_params;
+// testXhrEventParsing(xhrData, "new_email");
+// });
+// });
+
+// describe("ID-compatibility (new->old)", () => {
+// const gmail = new Gmail();
+// const validEmailLegacyId = "16a0d1f820d515e2";
+// const validEmailNewId = "msg-a:12345";
+// const invalidEmailNewId = "msg-a:12346";
+
+// const email = { foo: "bar" };
+// email.id = validEmailNewId;
+// email.legacy_email_id = validEmailLegacyId;
+// gmail.cache.emailIdCache[validEmailNewId] = email;
+// gmail.cache.emailLegacyIdCache[validEmailLegacyId] = email;
+
+// const elem = {
+// dataset: {
+// "messageId": "#" + validEmailNewId,
+// legacyMessageId: validEmailLegacyId
+// }
+// };
+// const domEmail = {
+// id: validEmailLegacyId,
+// $el: [ elem ]
+// };
+
+
+// it("Provides null from null-valued legacy ID", () => {
+// const res = gmail.helper.get.legacy_email_id(null);
+// assert.equal(null, res);
+// });
+
+// it("Provides legacy ID from legacy ID", () => {
+// const res = gmail.helper.get.legacy_email_id(validEmailLegacyId);
+// assert.equal(res, validEmailLegacyId);
+// });
+
+// it("Provides legacy ID from emailData object", () => {
+// const res = gmail.helper.get.legacy_email_id(email);
+// assert.equal(res, validEmailLegacyId);
+// });
+
+// it("Provides legacy ID from HTML element", () => {
+// const res = gmail.helper.get.legacy_email_id(elem);
+// assert.equal(res, validEmailLegacyId);
+// });
+
+// it("Provides legacy ID from DomEmail object", () => {
+// const res = gmail.helper.get.legacy_email_id(domEmail);
+// assert.equal(res, validEmailLegacyId);
+// });
+
+// it("Provides legacy ID from valid new-style ID", () => {
+// const res = gmail.helper.get.legacy_email_id(validEmailNewId);
+// assert.equal(res, validEmailLegacyId);
+// });
+
+// it("Returns null from invalid new-style ID (doesn't crash!)", () => {
+// const res = gmail.helper.get.legacy_email_id(invalidEmailNewId);
+// assert.equal(res, null);
+// });
+
+// it("Shows warning when provided new but expecting old", () => {
+// let warnInvoked = false;
+// let origWarnFunc = console.warn;
+// console.warn = () => {
+// warnInvoked = true;
+// };
+
+// let res = gmail.helper.get.legacy_email_id(validEmailNewId);
+
+// console.warn = origWarnFunc;
+// assert.equal(true, warnInvoked);
+// });
+// });
+
+// describe("ID-compatibility (old->new)", () => {
+// const gmail = new Gmail();
+// const validEmailLegacyId = "16a0d1f820d515e2";
+// const validEmailNewId = "msg-a:12345";
+// const invalidEmailLegacyid = "16a0d1f820d515e3";
+
+// const email = { foo: "bar" };
+// email.id = validEmailNewId;
+// email.legacy_email_id = validEmailLegacyId;
+// gmail.cache.emailIdCache[validEmailNewId] = email;
+// gmail.cache.emailLegacyIdCache[validEmailLegacyId] = email;
+
+// const elem = {
+// dataset: {
+// "messageId": "#" + validEmailNewId,
+// "legacyMessageId": validEmailLegacyId
+// }
+// };
+// const domEmail = {
+// id: validEmailLegacyId,
+// $el: [ elem ]
+// };
+
+// it("Provides null from null-valued ID", () => {
+// const res = gmail.helper.get.new_email_id(null);
+// assert.equal(null, res);
+// });
+
+// it("Provides new ID from new ID", () => {
+// const res = gmail.helper.get.new_email_id(validEmailNewId);
+// assert.equal(res, validEmailNewId);
+// });
+
+// it("Provides new ID from emailData object", () => {
+// const res = gmail.helper.get.new_email_id(email);
+// assert.equal(res, validEmailNewId);
+// });
+
+// it("Provides new ID from HTML element", () => {
+// const res = gmail.helper.get.new_email_id(elem);
+// assert.equal(res, validEmailNewId);
+// });
+
+// it("Provides new ID from DomEmail object", () => {
+// const res = gmail.helper.get.new_email_id(domEmail);
+// assert.equal(res, validEmailNewId);
+// });
+
+// it("Provides new ID from valid legacy-style ID", () => {
+// const res = gmail.helper.get.new_email_id(validEmailLegacyId);
+// assert.equal(res, validEmailNewId);
+// });
+
+// it("Returns null from invalid legacy-style ID (doesn't crash!)", () => {
+// const res = gmail.helper.get.new_email_id(invalidEmailLegacyid);
+// assert.equal(res, null);
+// });
+
+// it("Returns null on unrecognized input", () => {
+// const res = gmail.helper.get.new_email_id("jgkldfjgdfkljgdfkl");
+// assert.equal(null, res);
+// });
+
+// it("Shows warning when provided old but expecting new", () => {
+// let warnInvoked = false;
+// let origWarnFunc = console.warn;
+// console.warn = () => {
+// warnInvoked = true;
+// };
+
+// let res = gmail.helper.get.new_email_id(validEmailLegacyId);
+
+// console.warn = origWarnFunc;
+// assert.equal(true, warnInvoked);
+// });
+// });
+
+// describe("ID-compatibility (old->thread)", () => {
+// const gmail = new Gmail();
+// const validThreadId = "thread-a:r266633262821436756";
+// const validEmailNewId = "msg-a:12345";
+// const validEmailLegacyId = "16a0d1f820d515e2";
+
+// const email = {
+// thread_id: validThreadId,
+// id: validEmailNewId,
+// legacy_email_id: validEmailLegacyId
+// };
+// gmail.cache.emailIdCache[validEmailNewId] = email;
+// gmail.cache.emailLegacyIdCache[validEmailLegacyId] = email;
+
+// const emailElem = {
+// dataset: {
+// "messageId": "#" + validEmailNewId,
+// "legacyMessageId": validEmailLegacyId
+// }
+// };
+// const domEmail = {
+// id: validEmailLegacyId,
+// $el: [ emailElem ]
+// };
+
+// const threadElem = {
+// dataset: {
+// threadPermId: "#" + validThreadId
+// }
+// };
+// const domThread = {
+// $el: [ threadElem ]
+// };
+
+// it("Provides null from null-valued ID", () => {
+// const res = gmail.helper.get.thread_id(null);
+// assert.equal(null, res);
+// });
+
+// it("Provides thread ID from thread ID", () => {
+// const res = gmail.helper.get.thread_id(validThreadId);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Provides thread ID from emailData", () => {
+// const res = gmail.helper.get.thread_id(email);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Provides thread ID from new email ID", () => {
+// const res = gmail.helper.get.thread_id(validEmailNewId);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Provides thread ID from legacy email ID", () => {
+// const res = gmail.helper.get.thread_id(validEmailLegacyId);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Provides thread ID from DomThread object", () => {
+// const res = gmail.helper.get.thread_id(domThread);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Provides thread ID from DomEmail object", () => {
+// const res = gmail.helper.get.thread_id(domEmail);
+// assert.equal(res, validThreadId);
+// });
+
+// it("Returns null on unrecognized input", () => {
+// const res = gmail.helper.get.thread_id("u8gjkldejgkldfjklgdfjkl");
+// assert.equal(res, null);
+// });
+
+// it("Shows warning when provided email-id instead of thread-id", () => {
+// let warnInvoked = false;
+// let origWarnFunc = console.warn;
+// console.warn = () => {
+// warnInvoked = true;
+// };
+
+// let res = gmail.helper.get.thread_id(validEmailNewId);
+
+// console.warn = origWarnFunc;
+// assert.equal(true, warnInvoked);
+// });
+
+// it("Shows warning when provided legacy email-id instead of thread-id", () => {
+// let warnInvoked = false;
+// let origWarnFunc = console.warn;
+// console.warn = () => {
+// warnInvoked = true;
+// };
+
+// let res = gmail.helper.get.thread_id(validEmailLegacyId);
+
+// console.warn = origWarnFunc;
+// assert.equal(true, warnInvoked);
+// });
+// });
+
+// describe("Compose-email-parsing", () => {
+
+// it("Handles single thread id", () => {
+// var gmail = new Gmail(jquery);
+
+// var element = jquery('').find(".M9");
+// var compose = new gmail.dom.compose(element);
+
+// assert.equal(compose.thread_id(), "thread-f:1610056787031797158");
+// });
+
+// it("Handles thread id joined with message id", () => {
+// var gmail = new Gmail(jquery);
+
+// var element = jquery('').find(".M9");
+// var compose = new gmail.dom.compose(element);
+
+// assert.equal(compose.thread_id(), "thread-f:1610056787031797155|msg-f:1610056787031797158");
+// });
+// });
+
+// describe("Test tools for parsing XHR bv-request-payload-response", () => {
+
+// var xhrDataJSON = require("./testdata-parser-json/testdata-parser-bv-request-payload.json");
+// var gmail = new Gmail();
+// var parsed = gmail.tools.parse_bv_request_payload(xhrDataJSON);
+
+// it("Response is an array of 5 elements", () => {
+// assert.equal(Array.isArray(parsed),true);
+// assert.equal(parsed.length,5);
+// });
+
+// it("Handles Thread-1 Email-1 JSON consistently", () => {
+// assert.equal(parsed[0].id, "msg-a:r-5459297729901660292");
+// assert.equal(parsed[0].legacy_email_id, "171bb0399636172e");
+// assert.equal(parsed[0].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[0].smtp_id, "");
+// assert.equal(parsed[0].is_draft, false);
+// assert.equal(parsed[0].subject, "Working from home: The future of business is remote");
+// assert.equal(parsed[0].timestamp, 1587980507491);
+// assert.equal(parsed[0].content_html, "");
+// assert.deepStrictEqual(parsed[0].date, new Date("2020-04-27T09:41:47.491Z"));
+// assert.equal(parsed[0].from.address, 'elonm@gmail.com');
+// assert.equal(parsed[0].from.name, 'Elon' );
+// assert.equal((parsed[0].to).length, 0);
+// assert.equal((parsed[0].cc).length, 0);
+// assert.equal((parsed[0].bcc).length, 0);
+// assert.equal((parsed[0].attachments).length, 0);
+// });
+// it("Handles Thread-1 Email-2 JSON consistently", () => {
+// assert.equal(parsed[1].id, "msg-f:1665118316230599953");
+// assert.equal(parsed[1].legacy_email_id, "171bb04953ebe511");
+// assert.equal(parsed[1].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[1].smtp_id, "");
+// assert.equal(parsed[1].is_draft, false);
+// assert.equal(parsed[1].subject, "Working from home: The future of business is remote");
+// assert.equal(parsed[1].timestamp, 1587980571966);
+// assert.equal(parsed[1].content_html, "");
+// assert.deepStrictEqual(parsed[1].date, new Date("2020-04-27T09:42:51.966Z"));
+// assert.equal(parsed[1].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[1].from.name, 'Eric');
+// assert.equal((parsed[1].to).length, 0);
+// assert.equal((parsed[1].cc).length, 0);
+// assert.equal((parsed[1].bcc).length, 0);
+// assert.equal((parsed[1].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-1 JSON consistently", () => {
+// assert.equal(parsed[2].id, "msg-a:r-7004022322083187773");
+// assert.equal(parsed[2].legacy_email_id, "171bafdd8d3f48bb");
+// assert.equal(parsed[2].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[2].smtp_id, "");
+// assert.equal(parsed[2].is_draft, false);
+// assert.equal(parsed[2].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[2].timestamp, 1587980130515);
+// assert.equal(parsed[2].content_html, "");
+// assert.deepStrictEqual(parsed[2].date, new Date("2020-04-27T09:35:30.515Z"));
+// assert.equal(parsed[2].from.address, 'elonm@gmail.com');
+// assert.equal(parsed[2].from.name, 'Elon' );
+// assert.equal((parsed[2].to).length, 0);
+// assert.equal((parsed[2].cc).length, 0);
+// assert.equal((parsed[2].bcc).length, 0);
+// assert.equal((parsed[2].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-2 JSON consistently", () => {
+// assert.equal(parsed[3].id, "msg-f:1665117937823393243");
+// assert.equal(parsed[3].legacy_email_id, "171baff1391825db");
+// assert.equal(parsed[3].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[3].smtp_id, "");
+// assert.equal(parsed[3].is_draft, false);
+// assert.equal(parsed[3].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[3].timestamp, 1587980211089);
+// assert.equal(parsed[3].content_html, "");
+// assert.deepStrictEqual(parsed[3].date, new Date("2020-04-27T09:36:51.089Z"));
+// assert.equal(parsed[3].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[3].from.name, 'Eric' );
+// assert.equal((parsed[3].to).length, 0);
+// assert.equal((parsed[3].cc).length, 0);
+// assert.equal((parsed[3].bcc).length, 0);
+// assert.equal((parsed[3].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-3 JSON consistently", () => {
+// assert.equal(parsed[4].id, "msg-f:1665118117266291066");
+// assert.equal(parsed[4].legacy_email_id, "171bb01b00b9797a");
+// assert.equal(parsed[4].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[4].smtp_id, "");
+// assert.equal(parsed[4].is_draft, false);
+// assert.equal(parsed[4].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[4].timestamp, 1587980382219);
+// assert.equal(parsed[4].content_html, "");
+// assert.deepStrictEqual(parsed[4].date, new Date("2020-04-27T09:39:42.219Z"));
+// assert.equal(parsed[4].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[4].from.name, 'Eric' );
+// assert.equal((parsed[4].to).length, 0);
+// assert.equal((parsed[4].cc).length, 0);
+// assert.equal((parsed[4].bcc).length, 0);
+// assert.equal((parsed[4].attachments).length, 0);
+// });
+// });
+
+// describe("Test tools for parsing bv-embedded-data", () => {
+
+// var xhrDataJSON = require("./testdata-parser-json/testdata-parser-bv-embedded.json");
+// var gmail = new Gmail();
+// var parsed = gmail.tools.parse_bv_embedded_json(xhrDataJSON);
+
+// it("JSON Data is an array of 5 elements", () => {
+// assert.equal(Array.isArray(parsed),true);
+// assert.equal(parsed.length,5);
+// });
+
+// it("Handles Thread-1 Email-1 JSON consistently", () => {
+// assert.equal(parsed[0].id, "msg-a:r-5459297729901660292");
+// assert.equal(parsed[0].legacy_email_id, "171bb0399636172e");
+// assert.equal(parsed[0].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[0].smtp_id, "");
+// assert.equal(parsed[0].is_draft, false);
+// assert.equal(parsed[0].subject, "Working from home: The future of business is remote");
+// assert.equal(parsed[0].timestamp, 1587980507491);
+// assert.equal(parsed[0].content_html, "");
+// assert.deepStrictEqual(parsed[0].date, new Date("2020-04-27T09:41:47.491Z"));
+// assert.equal(parsed[0].from.address, 'elonm@gmail.com');
+// assert.equal(parsed[0].from.name, 'Elon' );
+// assert.equal((parsed[0].to).length, 0);
+// assert.equal((parsed[0].cc).length, 0);
+// assert.equal((parsed[0].bcc).length, 0);
+// assert.equal((parsed[0].attachments).length, 0);
+// });
+// it("Handles Thread-1 Email-2 JSON consistently", () => {
+// assert.equal(parsed[1].id, "msg-f:1665118316230599953");
+// assert.equal(parsed[1].legacy_email_id, "171bb04953ebe511");
+// assert.equal(parsed[1].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[1].smtp_id, "");
+// assert.equal(parsed[1].is_draft, false);
+// assert.equal(parsed[1].subject, "Working from home: The future of business is remote");
+// assert.equal(parsed[1].timestamp, 1587980571966);
+// assert.equal(parsed[1].content_html, "");
+// assert.deepStrictEqual(parsed[1].date, new Date("2020-04-27T09:42:51.966Z"));
+// assert.equal(parsed[1].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[1].from.name, 'Eric');
+// assert.equal((parsed[1].to).length, 0);
+// assert.equal((parsed[1].cc).length, 0);
+// assert.equal((parsed[1].bcc).length, 0);
+// assert.equal((parsed[1].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-1 JSON consistently", () => {
+// assert.equal(parsed[2].id, "msg-a:r-7004022322083187773");
+// assert.equal(parsed[2].legacy_email_id, "171bafdd8d3f48bb");
+// assert.equal(parsed[2].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[2].smtp_id, "");
+// assert.equal(parsed[2].is_draft, false);
+// assert.equal(parsed[2].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[2].timestamp, 1587980130515);
+// assert.equal(parsed[2].content_html, "");
+// assert.deepStrictEqual(parsed[2].date, new Date("2020-04-27T09:35:30.515Z"));
+// assert.equal(parsed[2].from.address, 'elonm@gmail.com');
+// assert.equal(parsed[2].from.name, 'Elon' );
+// assert.equal((parsed[2].to).length, 0);
+// assert.equal((parsed[2].cc).length, 0);
+// assert.equal((parsed[2].bcc).length, 0);
+// assert.equal((parsed[2].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-2 JSON consistently", () => {
+// assert.equal(parsed[3].id, "msg-f:1665117937823393243");
+// assert.equal(parsed[3].legacy_email_id, "171baff1391825db");
+// assert.equal(parsed[3].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[3].smtp_id, "");
+// assert.equal(parsed[3].is_draft, false);
+// assert.equal(parsed[3].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[3].timestamp, 1587980211089);
+// assert.equal(parsed[3].content_html, "");
+// assert.deepStrictEqual(parsed[3].date, new Date("2020-04-27T09:36:51.089Z"));
+// assert.equal(parsed[3].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[3].from.name, 'Eric' );
+// assert.equal((parsed[3].to).length, 0);
+// assert.equal((parsed[3].cc).length, 0);
+// assert.equal((parsed[3].bcc).length, 0);
+// assert.equal((parsed[3].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-3 JSON consistently", () => {
+// assert.equal(parsed[4].id, "msg-f:1665118117266291066");
+// assert.equal(parsed[4].legacy_email_id, "171bb01b00b9797a");
+// assert.equal(parsed[4].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[4].smtp_id, "");
+// assert.equal(parsed[4].subject, "Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[4].timestamp, 1587980382219);
+// assert.equal(parsed[4].content_html, "");
+// assert.deepStrictEqual(parsed[4].date, new Date("2020-04-27T09:39:42.219Z"));
+// assert.equal(parsed[4].from.address, 'Eric@gmail.com');
+// assert.equal(parsed[4].from.name, 'Eric' );
+// assert.equal((parsed[4].to).length, 0);
+// assert.equal((parsed[4].cc).length, 0);
+// assert.equal((parsed[4].bcc).length, 0);
+// assert.equal((parsed[4].attachments).length, 0);
+// });
+
+// });
+
+describe("Test tools for parsing fd-embedded-data", () => {
+
+ var xhrDataJSON = require("./testdata-parser-json/testdata-parser-fd-embedded.json");
+ var gmail = new Gmail(false);
+ var parsed = gmail.tools.parse_fd_embedded_json(xhrDataJSON);
+
+ it("JSON Data is an array of 5 elements", () => {
+ assert.equal(Array.isArray(parsed),true);
+ assert.equal(parsed.length,5);
});
- it("Masks failure in probing function, when accesing non-existant data", () => {
- const testObj = {
- "a": "a"
- };
- let result = testee(testObj, (item) => {
- return item[0]["a"].substring(5) === "z";
- });
- assert.equal(0, result.length);
+ it("Handles Thread-1 Email-1 JSON consistently", () => {
+ assert.equal(parsed[0].id, "msg-f:1743836977043622489");
+ assert.equal(parsed[0].legacy_email_id, "18335a7dcae04a59");
+ assert.equal(parsed[0].thread_id, "thread-f:1743836977043622489|msg-f:1743836977043622489");
+ assert.equal(parsed[0].smtp_id, "<491e0008-2936-f0e2-171a-3d696268b5b7@secure.kjonigsen.net>");
+ assert.equal(parsed[0].is_draft, false);
+ assert.equal(parsed[0].subject, "Test email 4");
+ assert.equal(parsed[0].timestamp, 1663052537006);
+ assert.equal(parsed[0].content_html, "\r\n \r\n\r\n \r\n \r\n \r\n\r\n");
+ assert.deepStrictEqual(parsed[0].date, new Date("2022-09-13T07:02:17.006Z"));
+ assert.equal(parsed[0].from.address, 'jostein@secure.kjonigsen.net');
+ assert.equal(parsed[0].from.name, 'Jostein Kjønigsen' );
+ assert.equal((parsed[0].to).length, 1);
+ assert.equal((parsed[0].cc).length, 0);
+ assert.equal((parsed[0].bcc).length, 0);
+
+ assert.equal((parsed[0].attachments).length, 1);
+ assert.equal((parsed[0].attachments[0].attachment_id), "0.0.2");
+ assert.equal((parsed[0].attachments[0].name), "invite.ics");
+ assert.equal((parsed[0].attachments[0].type), "application/ics");
+ assert.equal((parsed[0].attachments[0].url), "https://mail.google.com/mail/?ui=0&ik=99e3eb73b5&attid=0.0.2&permmsgid=msg-f:1743836977043622489&th=18335a7f90a24d19&view=att&zw");
+ assert.equal((parsed[0].attachments[0].size), 1564);
});
-
- it("Can extract arrays when predicate matches", () => {
- const expected = [1,2,3];
- const testObj = {
- "a": expected
- };
- let result = testee(testObj, Array.isArray);
- assert.equal(1, result.length);
- assert.equal(expected, result[0]);
- });
-
- it("Can extract node when root-object is array", () => {
- const testObj = [ "boo", "abc" ];
- let result = testee(testObj, (item) => { return item === "abc"; });
- assert.equal(1, result.length);
- assert.equal("abc", result[0]);
- });
-});
-
-describe("New Gmail event-triggering", () => {
- const gmail = new Gmail();
- const testCase = (data, asserts) => {
- const events = {};
- const params = {
- body_params: JSON.parse(data)
- };
- // we must force, because requset_payload tries to do URL detection
- gmail.tools.parse_request_payload(params, events, true);
- asserts(events);
- };
-
- // TODO: refactor these tests into the same form as those below.
- it("Triggers for send_email", () => {
- testCase(testData.new_gmail_send_email_data, (events) => {
- assert.ok(events.send_message);
- });
- });
- it("Triggers for archive", () => {
- testCase(testData.new_gmail_archive_action_body_params, (events) => {
- assert.ok(events.archive);
- });
- });
- it("Triggers for new_email", () => {
- testCase(testData.new_gmail_new_email_body_params, (events) => {
- assert.ok(events.new_email);
- });
- });
-
- // it("Extracts compose-id", () => {
-
- // });
+// it("Handles Thread-1 Email-2 JSON consistently", () => {
+// assert.equal(parsed[1].id, "msg-f:1665117937823393243");
+// assert.equal(parsed[1].legacy_email_id, "171baff1391825db");
+// assert.equal(parsed[1].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[1].smtp_id, "<5b58a962565085f4c392f5efdc8e14c6@gmail.com>");
+// assert.equal(parsed[1].is_draft, false);
+// assert.equal(parsed[1].subject, "Re: Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[1].timestamp, 1587980211089);
+// assert.equal(parsed[1].content_html, "\r\n
Le 27.04.2020 11:35, Elon a écrit :
\r\n
\r\nSix months of blood, sweat and development tears have gone in Ubuntu
20.04 LTS (which is codenamed "Focal Fossa") resulting in substantial
set of improvements that improve just about every part of the OS, from
boot speed to app appearance to bundled software.
\r\n
\r\n
What a good news !!
\r\n
\r\n
\r\n
\r\n
\r\n");
+// assert.deepStrictEqual(parsed[1].date, new Date("2020-04-27T09:36:51.089Z"));
+// assert.equal(parsed[1].from.address, 'billg@gmail.com');
+// assert.equal(parsed[1].from.name, 'Bill' );
+// assert.equal((parsed[1].to).length, 1);
+// assert.equal((parsed[1].cc).length, 0);
+// assert.equal((parsed[1].bcc).length, 0);
+
+// assert.equal((parsed[1].attachments).length, 1);
+// assert.equal((parsed[1].attachments[0].attachment_id), "0.1");
+// assert.equal((parsed[1].attachments[0].name), "Ubuntu_20.04.txt");
+// assert.equal((parsed[1].attachments[0].type), "text/plain");
+// assert.equal((parsed[1].attachments[0].url), "https://mail.google.com/mail/?ui=2&ik=74384930e0&attid=0.1&permmsgid=msg-f:1665117937823393243&th=171baff1391825db&view=att&zw");
+// assert.equal((parsed[1].attachments[0].size), 1017);
+// });
+// it("Handles Thread-1 Email-3 JSON consistently", () => {
+// assert.equal(parsed[2].id, "msg-f:1665118117266291066");
+// assert.equal(parsed[2].legacy_email_id, "171bb01b00b9797a");
+// assert.equal(parsed[2].thread_id, "thread-a:r-7005674805299871901");
+// assert.equal(parsed[2].smtp_id, "");
+// assert.equal(parsed[2].is_draft, false);
+// assert.equal(parsed[2].subject, "Re: Ubuntu 20.04 Download Link & New Features (Updated)");
+// assert.equal(parsed[2].timestamp, 1587980382219);
+// assert.equal(parsed[2].content_html, "\r\n
Le 27.04.2020 11:35, Elon a écrit :
\r\n
\r\nSix months of blood, sweat and development tears have gone in Ubuntu
20.04 LTS (which is codenamed "Focal Fossa") resulting in substantial
set of improvements that improve just about every part of the OS, from
boot speed to app appearance to bundled software.
\r\n
\r\n
What a good news !!
\r\n
\r\n\r\n
\r\n");
+// assert.deepStrictEqual(parsed[2].date, new Date("2020-04-27T09:39:42.219Z"));
+// assert.equal(parsed[2].from.address, 'billg@gmail.com');
+// assert.equal(parsed[2].from.name, 'Bill' );
+// assert.equal((parsed[2].to).length, 1);
+// assert.equal((parsed[2].cc).length, 4);
+// assert.equal((parsed[2].bcc).length, 0);
+
+// assert.equal((parsed[2].attachments).length, 1);
+// assert.equal((parsed[2].attachments[0].attachment_id), "0.1");
+// assert.equal((parsed[2].attachments[0].name), "Ubuntu_20.04.txt");
+// assert.equal((parsed[2].attachments[0].type), "text/plain");
+// assert.equal((parsed[2].attachments[0].url), "https://mail.google.com/mail/?ui=2&ik=74384930e0&attid=0.1&permmsgid=msg-f:1665118117266291066&th=171bb01b00b9797a&view=att&zw");
+// assert.equal((parsed[2].attachments[0].size), 1017);
+// });
+
+// it("Handles Thread-2 Email-1 JSON consistently", () => {
+// assert.equal(parsed[3].id, "msg-a:r-5459297729901660292");
+// assert.equal(parsed[3].legacy_email_id, "171bb0399636172e");
+// assert.equal(parsed[3].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[3].smtp_id, "");
+// assert.equal(parsed[3].is_draft, false);
+// assert.equal(parsed[3].subject, "Working from home: The future of business is remote");
+// assert.equal(parsed[3].timestamp, 1587980507491);
+// assert.equal(parsed[3].content_html, 'Look at that :
\n
\nhttps://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/
\n');
+// assert.deepStrictEqual(parsed[3].date, new Date("2020-04-27T09:41:47.491Z"));
+// assert.equal(parsed[3].from.address, 'elonm@gmail.com');
+// assert.equal(parsed[3].from.name, 'Elon' );
+// assert.equal((parsed[3].to).length, 2);
+// assert.equal((parsed[3].cc).length, 2);
+// assert.equal((parsed[3].bcc).length,2);
+
+// assert.equal((parsed[3].attachments).length, 1);
+// assert.equal((parsed[3].attachments[0].attachment_id), "0.1");
+// assert.equal((parsed[3].attachments[0].name), "work.txt");
+// assert.equal((parsed[3].attachments[0].type), "text/plain");
+// assert.equal((parsed[3].attachments[0].url), "https://mail.google.com/mail/?ui=2&ik=74384930e0&attid=0.1&permmsgid=msg-a:r-5459297729901660292&th=171bb0399636172e&view=att&realattid=f_k9ial9ll0&zw");
+// assert.equal((parsed[3].attachments[0].size), 278);
+// });
+// it("Handles Thread-2 Email-2 JSON consistently", () => {
+// assert.equal(parsed[4].id, "msg-f:1665118316230599953");
+// assert.equal(parsed[4].legacy_email_id, "171bb04953ebe511");
+// assert.equal(parsed[4].thread_id, "thread-a:r873907427374440696");
+// assert.equal(parsed[4].smtp_id, "<9d1446ea46e626b2fb391c5a3e047b17@gmail.com>");
+// assert.equal(parsed[4].is_draft, false);
+// assert.equal(parsed[4].subject, "Re: Working from home: The future of business is remote");
+// assert.equal(parsed[4].timestamp, 1587980571966);
+// assert.equal(parsed[4].content_html, "\r\n
Le 27.04.2020 11:41, Elon a écrit :
\r\n
\r\n\r\n
\r\n
Sure
\r\n
\r\n\r\n
\r\n");
+// assert.deepStrictEqual(parsed[4].date, new Date("2020-04-27T09:42:51.966Z"));
+// assert.equal(parsed[4].from.address, 'billg@gmail.com');
+// assert.equal(parsed[4].from.name, 'Bill');
+// assert.equal((parsed[4].to).length, 1);
+// assert.equal((parsed[4].cc).length, 4);
+// assert.equal((parsed[4].bcc).length, 0);
+
+// assert.equal((parsed[4].attachments).length, 1);
+// assert.equal((parsed[4].attachments[0].attachment_id), "0.1");
+// assert.equal((parsed[4].attachments[0].name), "work.txt");
+// assert.equal((parsed[4].attachments[0].type), "text/plain");
+// assert.equal((parsed[4].attachments[0].url), "https://mail.google.com/mail/?ui=2&ik=74384930e0&attid=0.1&permmsgid=msg-f:1665118316230599953&th=171bb04953ebe511&view=att&zw");
+// assert.equal((parsed[4].attachments[0].size), 278);
+// });
});
-describe("New Gmail event-parsing", () => {
- const gmail = new Gmail();
- const data = JSON.parse(testData.new_gmail_archive_action_body_params);
- const threads = gmail.tools.extract_from_graph(data, gmail.check.data.is_thread);
- const threadData = threads.map(thread => gmail.tools.get_thread_data(thread))[0];
-
- let testXhrEventParsing = function (jsonXhrData, eventName) {
- const api = new Gmail();
- const xhrData = JSON.parse(jsonXhrData);
-
- const threads = api.tools.extract_from_graph(xhrData, api.check.data.is_thread);
- const actionType = api.tools.check_event_type(threads[0]);
-
- assert.equal(eventName, actionType);
- };
-
- it("parses archived messages", () => {
- const xhrData = testData.new_gmail_archive_action_body_params;
- testXhrEventParsing(xhrData, "archive");
- });
-
- it("parses deleted messages", () => {
- const xhrData = testData.new_gmail_delete_action_body_params;
- testXhrEventParsing(xhrData, "delete");
- });
-
- it("parses read messages", () => {
- const xhrData = testData.new_gmail_read_action_body_params;
- testXhrEventParsing(xhrData, "read");
- });
-
- it("parses unread messages", () => {
- const xhrData = testData.new_gmail_unread_action_body_params;
- testXhrEventParsing(xhrData, "unread");
- });
-
- it("parses open_email messages", () => {
- const xhrData = testData.new_gmail_open_email_action_body_params;
- testXhrEventParsing(xhrData, "open_email");
- });
-
- it("parses new_email message", () => {
- const xhrData = testData.new_gmail_new_email_body_params;
- testXhrEventParsing(xhrData, "new_email");
- });
-});
+// describe("Test tools for parsing fd-request-data", () => {
+
+// var xhrDataJSON = require("./testdata-parser-json/testdata-parser-fd-request.json");
+// var gmail = new Gmail();
+// var parsed = gmail.tools.parse_fd_request_payload(xhrDataJSON);
+
+// it("JSON Data is an array of 2 elements", () => {
+// assert.equal(Array.isArray(parsed), true);
+// assert.equal(parsed.length, 2);
+// });
+
+// it("Handles Thread-1 Email-1 JSON consistently", () => {
+// assert.equal(parsed[0].id, "msg-a:r-4871072856822866136");
+// assert.equal(parsed[0].legacy_email_id, "17c3d9041ec7d0a5");
+// assert.equal(parsed[0].thread_id, "thread-a:r-4872725344334517560");
+// assert.equal(parsed[0].smtp_id, "");
+// assert.equal(parsed[0].is_draft, true);
+// assert.equal(parsed[0].subject, "test subject");
+// assert.equal(parsed[0].timestamp, 1633120436716);
+// assert.equal(parsed[0].content_html, "
\r\n");
+// assert.deepStrictEqual(parsed[0].date, new Date("2021-10-01T20:33:56.716Z"));
+// assert.equal(parsed[0].from.address, 'user@gmail.com');
+// assert.equal(parsed[0].from.name, 'First Last');
+// assert.equal((parsed[0].to).length, 0);
+// assert.equal((parsed[0].cc).length, 0);
+// assert.equal((parsed[0].bcc).length, 0);
+// assert.equal((parsed[0].attachments).length, 0);
+// });
+// it("Handles Thread-2 Email-1 JSON consistently", () => {
+// assert.equal(parsed[1].id, "msg-a:r-4871072856822866136");
+// assert.equal(parsed[1].legacy_email_id, "17c3d9364dec527d");
+// assert.equal(parsed[1].thread_id, "thread-a:r-4872725344334517560");
+// assert.equal(parsed[1].smtp_id, "");
+// assert.equal(parsed[1].is_draft, false);
+// assert.equal(parsed[1].subject, "test subject");
+// assert.equal(parsed[1].timestamp, 1633120642270);
+// assert.equal(parsed[1].content_html, "aaa
\r\n");
+// assert.deepStrictEqual(parsed[1].date, new Date("2021-10-01T20:37:22.270Z"));
+// assert.equal(parsed[1].from.address, 'user@gmail.com');
+// assert.equal(parsed[1].from.name, 'First Last');
+// assert.equal((parsed[1].to).length, 1);
+// assert.equal((parsed[1].cc).length, 0);
+// assert.equal((parsed[1].bcc).length, 0);
+// assert.equal((parsed[1].attachments).length, 0);
+// });
+
+// });
+
+// describe("Test parsing logged in accounts data", () => {
+// const mlaDataJSON = require("./testdata-parser-json/testdata-parser-mla.json");
+// const gmail = new Gmail();
+// gmail.tracker.mla = mlaDataJSON;
+
+// it("Handles mla data correctly", () => {
+// const result = gmail.get.loggedin_accounts();
+
+// assert.equal(result.length, 4);
+// assert.equal(result[0].name, "Gmail Dev");
+// assert.equal(result[0].email, "user2@gsuite2.com");
+// assert.equal(result[0].index, 3);
+// assert.equal(result[1].name, "Primary One");
+// assert.equal(result[1].email, "primary@gmail.com");
+// assert.equal(result[1].index, 0);
+// assert.equal(result[2].name, "Стефанія Мамо");
+// assert.equal(result[2].email, "mamo.stefania@gmail.com");
+// assert.equal(result[2].index, 1);
+// assert.equal(result[3].name, "Jack Sparrow");
+// assert.equal(result[3].email, "Jack.Sparrow@gsuite1.net");
+// assert.equal(result[3].index, 2);
+// })
+// });
diff --git a/test/test.stacking.js.disabled b/test/test.stacking.js.disabled
new file mode 100644
index 00000000..40ee50fa
--- /dev/null
+++ b/test/test.stacking.js.disabled
@@ -0,0 +1,131 @@
+"use strict";
+
+let assert = require("assert");
+let jsdom = require("jsdom");
+let jquery = require("jquery")(new jsdom.JSDOM().window);
+let GmailOld = require("gmail-js").Gmail;
+let Gmail = require("../src/gmail").Gmail;
+
+let testData = require("./testdata-parser.js");
+
+function XMLHttpRequestMock() {}
+XMLHttpRequestMock.prototype.open = (method, url, async, user, password) => {
+ // console.log('executing original open XHR method...');
+};
+XMLHttpRequestMock.prototype.send = (body) => {
+ // console.log('executing original send XHR method...');
+};
+
+describe("New Gmail event-triggering(in case of stacked current gmail.js instances)", () => {
+ let gmail1, gmail2, gmail3;
+
+ beforeEach(() => {
+ const window = new jsdom.JSDOM().window;
+ global.window = window;
+ global.performance = window.performance;
+ window["GM_SPT_ENABLED"] = "true"; // for new data layer
+
+ // inner gmail.js instance
+ gmail1 = new Gmail(jquery);
+ // middle gmail.js instance
+ gmail2 = new Gmail(jquery);
+ // outer gmail.js instance
+ gmail3 = new Gmail(jquery);
+
+ global.document = window.document; // done after the instantiations to avoid initial XHR patching
+
+ gmail1.helper.get_xhr_window = gmail2.helper.get_xhr_window = gmail3.helper.get_xhr_window = function() {
+ return {
+ XMLHttpRequest: XMLHttpRequestMock
+ };
+ };
+ });
+
+ // it("Triggers for send_email", () => {
+ // try {
+ // let sendMessageTriggered = '';
+ // // set event listeners
+ // gmail1.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'c';
+ // });
+ // gmail2.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'b';
+ // });
+ // gmail3.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'a';
+ // });
+
+ // // trigger XHR call
+ // const mockedRequest = new XMLHttpRequestMock();
+ // mockedRequest.open('POST', 'https://example.web.email.client.com/sync/u/0/i/s?hl=en&c=21');
+ // mockedRequest.send(testData.new_gmail_sent_email_json);
+
+ // assert.equal(sendMessageTriggered, 'abc', 'Not all "send_message" event handlers were triggered.');
+ // } catch (e) {
+ // assert.fail(e);
+ // }
+ // });
+
+ afterEach(() => {
+ global.document = undefined;
+ });
+});
+
+describe("New Gmail event-triggering(in case of stacked old & current gmail.js instances)", () => {
+ let gmail1, gmail2, gmail3;
+
+ beforeEach(() => {
+ const window = new jsdom.JSDOM().window;
+ global.window = window;
+ global.performance = window.performance;
+ window["GM_SPT_ENABLED"] = "true"; // for new data layer
+
+ /**
+ * GmailOld(outer) -> Gmail(inner)(present test case) works
+ * Gmail(outer) -> GmailOld(inner) currently breaks for GmailOld(unless some cleanup is done in current version, before sending the original request)
+ */
+ // inner gmail.js instance
+ gmail1 = new Gmail(jquery);
+ // middle gmail.js instance
+ gmail2 = new Gmail(jquery);
+ // outer gmail.js instance
+ gmail3 = new GmailOld(jquery);
+
+ global.document = window.document; // done after the instantiations, to avoid the initial XHR patching
+
+ gmail1.helper.get_xhr_window = gmail2.helper.get_xhr_window = gmail3.helper.get_xhr_window = function() {
+ return {
+ XMLHttpRequest: XMLHttpRequestMock
+ };
+ };
+ });
+
+ // it("Triggers for send_email", () => {
+ // try {
+ // let sendMessageTriggered = '';
+ // // set event listeners
+ // gmail1.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'c';
+ // });
+ // gmail2.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'b';
+ // });
+ // gmail3.observe.before('send_message', function (url, body, data, xhr) {
+ // sendMessageTriggered += 'a';
+ // });
+
+ // // trigger XHR call
+ // const mockedRequest = new XMLHttpRequestMock();
+ // mockedRequest.open('POST', 'https://example.web.email.client.com/sync/u/0/i/s?hl=en&c=21');
+ // mockedRequest.send(testData.new_gmail_sent_email_json);
+
+ // assert.equal(sendMessageTriggered, 'abc', 'Not all "send_message" mixed event handlers were triggered.');
+ // } catch (e) {
+ // assert.fail(e);
+ // }
+ // });
+
+ afterEach(() => {
+ global.document = undefined;
+ });
+});
diff --git a/test/test.tools.js b/test/test.tools.js
index 6970f11c..c44e87d4 100644
--- a/test/test.tools.js
+++ b/test/test.tools.js
@@ -1,7 +1,7 @@
"use strict";
let assert = require('assert');
let Gmail = require('../src/gmail').Gmail;
-let gmail = new Gmail();
+let gmail = new Gmail(false);
const testData = require("./testdata-parser.js");
@@ -48,31 +48,39 @@ describe("Monkeypatching", () => {
});
});
-describe("Test tools for parsing new gmail body_params", () => {
- const gmail = new Gmail();
- const data = JSON.parse(testData.new_gmail_archive_action_body_params);
- const threads = gmail.tools.extract_from_graph(data, gmail.check.data.is_thread);
- const threadData = threads.map(thread => gmail.tools.get_thread_data(thread))[0];
+// describe("Test tools for parsing new gmail body_params", () => {
+// const gmail = new Gmail();
+// const data = JSON.parse(testData.new_gmail_archive_action_body_params);
+// const threads = gmail.tools.extract_from_graph(data, gmail.check.data.is_thread);
+// const threadData = threads.map(thread => gmail.tools.get_thread_data(thread))[0];
- it("get thread id", () => {
- const thread = gmail.tools.get_thread_id(threads[0]);
+// it("get thread id", () => {
+// const thread = gmail.tools.get_thread_id(threads[0]);
- assert.equal(thread, 'thread-f:1603171109786600032');
- });
+// assert.equal(thread, 'thread-f:1603171109786600032');
+// });
- it("get thread data", () => {
- const mockThreadData = threads[0][2][7];
- const threadData = gmail.tools.get_thread_data(threads[0]);
- console.log(threadData);
+// it("get thread data", () => {
+// const mockThreadData = threads[0][2][7];
+// const threadData = gmail.tools.get_thread_data(threads[0]);
- assert.deepEqual(threadData, mockThreadData);
- });
+// assert.deepEqual(threadData, mockThreadData);
+// });
- it("get messages ids", () => {
- const mockMessageIds = ['msg-f:1603171109786600032', 'msg-f:1603245801543734539', 'msg-f:1603245862071354412', 'msg-f:1603246018478443087', 'msg-f:1603256094012730022', 'msg-f:1603256564311088576', 'msg-f:1603256665279246114', 'msg-f:1603256682384715664', 'msg-f:1603376719891477511', 'msg-f:1603376909485932601', 'msg-f:1603376994923202634', 'msg-f:1603380395240179639'];
- const messagesIds = gmail.tools.get_message_ids(threadData);
+// it("get messages ids", () => {
+// const mockMessageIds = ['msg-f:1603171109786600032', 'msg-f:1603245801543734539', 'msg-f:1603245862071354412', 'msg-f:1603246018478443087', 'msg-f:1603256094012730022', 'msg-f:1603256564311088576', 'msg-f:1603256665279246114', 'msg-f:1603256682384715664', 'msg-f:1603376719891477511', 'msg-f:1603376909485932601', 'msg-f:1603376994923202634', 'msg-f:1603380395240179639'];
+// const messagesIds = gmail.tools.get_message_ids(threadData);
- assert.equal(messagesIds.length, 12);
- assert.deepEqual(messagesIds, mockMessageIds);
- });
-});
+// assert.equal(messagesIds.length, 12);
+// assert.deepEqual(messagesIds, mockMessageIds);
+// });
+
+// it("apply label event", () => {
+// const threads_apply_label_data = JSON.parse(testData.new_gmail_apply_label_action_body_params);
+// const threads_data = gmail.tools.extract_from_graph(threads_apply_label_data, gmail.check.data.is_thread);
+// const apply_label_event = "label";
+// const actionType = gmail.tools.check_event_type(threads_data[0]);
+
+// assert.equal(actionType, apply_label_event);
+// });
+// });
diff --git a/test/testdata-parser-json/testdata-parser-bv-embedded.json b/test/testdata-parser-json/testdata-parser-bv-embedded.json
new file mode 100644
index 00000000..c3c8f759
--- /dev/null
+++ b/test/testdata-parser-json/testdata-parser-bv-embedded.json
@@ -0,0 +1,457 @@
+{
+ "1": {
+ "1": [{
+ "2": "thread-a:r873907427374440696",
+ "3": "9223370448874203841",
+ "4": "Working from home: The future of business is remote",
+ "5": {
+ "1": "Working from home: The future of business is remote",
+ "2": "Le 27.04.2020 11:41, Elon a \u00e9crit : Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/ Sure",
+ "3": "1587980572051",
+ "4": "thread-a:r873907427374440696",
+ "5": [{
+ "1": "msg-a:r-5459297729901660292",
+ "2": {
+ "1": 1,
+ "2": "elonm@gmail.com",
+ "3": "Elon"
+ },
+ "7": "1587980506989",
+ "10": "Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/",
+ "11": ["^a", "^all", "^f", "^f_bt", "^io_lr", "^o"],
+ "12": [{
+ "1": "text/plain",
+ "2": "work.txt",
+ "3": "278",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-a:r-5459297729901660292\u0026th\u003d171bb0399636172e\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "55fc38f1_52e78411_3774f559_d670a76b_62b66717",
+ "9": "ANGjdJ-hf1V7Q95MZJqK2jUy8ocdUnWN2TmqcXqRfsuI62nKXqSlMV7qmQ3huHkHdQ7661IlX5THnhZPIkiM3WbMW5I7kkUx1Vjcpr3Xu43HqCGyBqU9ba2p85IWXKg"
+ },
+ "11": 1
+ }],
+ "18": "1587980507491",
+ "30": {
+ "7": {
+ "1": "21660258"
+ },
+ "8": [21660258],
+ "10": 1
+ },
+ "31": "1587980507491",
+ "44": 0,
+ "56": "171bb0399636172e"
+ }, {
+ "1": "msg-f:1665118316230599953",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980572051",
+ "10": "Le 27.04.2020 11:41, Elon a \u00e9crit : Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/ Sure",
+ "11": ["^all", "^i", "^iim", "^io_im", "^io_lr", "^o", "^p_ag", "^smartlabel_personal", "^sq_ig_i_personal"],
+ "12": [{
+ "1": "text/plain",
+ "2": "work.txt",
+ "3": "278",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665118316230599953\u0026th\u003d171bb04953ebe511\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "55fc38f1_52e78411_3774f559_d670a76b_62b66717",
+ "9": "ANGjdJ_bCJGX4pYo-KsltojoThzMbGTNrje4ncEk43zD85qkRr6zzweWZiQLsLG6pIbflY63rnX8UVRb0JTdfzKCFzO8_RBgk6VhkPj-CNq1312QMiWDgl-RYzoVXTA"
+ },
+ "11": 1
+ }],
+ "13": {
+ "28": "msg-f:1665118316230599953",
+ "31": [{
+ "1": {
+ "1": 0,
+ "2": "article"
+ },
+ "2": {
+ "1": [{
+ "1": "https://ci3.googleusercontent.com/proxy/VjhEslX1v9LhdeKFxo3OZLW5makCxJR8mPRerkuZJe2IcflH9QQCysUGsePSYVO1hCU1SCcKFOOi1hq8CLn_BO5v7JDU2OjTjjXhp2a7ihDEios1E3XZesuiJffUZ7T9FxF3fnLM6xxxoUsIGJceYzD3jXi4kDpZht7CblaTGl-7WuKx2MG5aAOi8f7rJbs7PekUWgfLW3Lb2qJrRBVQtSAU8rXu560SVET-a9d4Vi5HHJIhcgBAYoTL9Q",
+ "7": 1,
+ "11": 1
+ }],
+ "2": {
+ "1": [{
+ "1": "Working from home: The future of business is remote | ZDNet"
+ }]
+ },
+ "3": [{
+ "1": [{
+ "1": "www.zdnet.com"
+ }]
+ }]
+ },
+ "4": "5152721027681343705",
+ "5": {
+ "1": "4503599627370495"
+ },
+ "6": 1
+ }]
+ },
+ "16": "\u003cCAHqB\u003dtDjJtq9QsjipXxqx4UE07nmSkDib1XqH0Wi0R7JU8vEmg@mail.gmail.com\u003e",
+ "18": "1587980571966",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.87796235
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980571966",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171bb04953ebe511"
+ }],
+ "8": "1587980507468",
+ "14": 0.87796235,
+ "15": {
+ "1": [{
+ "1": "",
+ "2": "billg@gmail.com"
+ }, {
+ "1": "",
+ "2": "jeffb@gmail.com"
+ }, {
+ "1": "",
+ "2": "larrye@gmail.com"
+ }, {
+ "1": "",
+ "2": "larryp@gmail.com"
+ }],
+ "2": [{
+ "1": "",
+ "2": "sergeyb@gmail.com"
+ }, {
+ "1": "",
+ "2": "markz@gmail.com"
+ }]
+ },
+ "17": 0,
+ "19": 1,
+ "20": "171bb02371f0da52"
+ },
+ "7": "2",
+ "11": 1,
+ "13": "1587980571966"
+ }, {
+ "2": "thread-a:r-7005674805299871901",
+ "3": "9223370448874393588",
+ "4": "Ubuntu 20.04 Download Link \u0026 New Features (Updated)",
+ "5": {
+ "1": "Ubuntu 20.04 Download Link \u0026 New Features (Updated)",
+ "2": "Le 27.04.2020 11:35, Elon a \u00e9crit : Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \"Focal Fossa\") resulting in substantial set of",
+ "3": "1587980382357",
+ "4": "thread-a:r-7005674805299871901",
+ "5": [{
+ "1": "msg-a:r-7004022322083187773",
+ "2": {
+ "1": 1,
+ "2": "elonm@gmail.com",
+ "3": "Elon"
+ },
+ "7": "1587980129841",
+ "10": "Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \u201cFocal Fossa\u201d) resulting in substantial set of improvements that improve just about every part of the",
+ "11": ["^a", "^all", "^f", "^f_bt", "^io_lr", "^o"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-a:r-7004022322083187773\u0026th\u003d171bafdd8d3f48bb\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ-fjNZwhzD_nrsZfJMFZmODWMzXm9t_cqII-_2inSmWjPKaHtvn2ZogqoRvwX4soZQwIvPfNFrgrJ1vZ4e4p2-As4Y6BGqyF-ibts7W8E8CmBdW9pvf_cWqBTk"
+ },
+ "11": 1
+ }],
+ "18": "1587980130515",
+ "30": {
+ "7": {
+ "1": "21660258"
+ },
+ "8": [21660258],
+ "10": 1
+ },
+ "31": "1587980130515",
+ "44": 0,
+ "56": "171bafdd8d3f48bb"
+ }, {
+ "1": "msg-f:1665117937823393243",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980211022",
+ "11": ["^all", "^i", "^iim", "^io_im", "^io_lr", "^o", "^smartlabel_personal", "^sq_ig_i_personal"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665117937823393243\u0026th\u003d171baff1391825db\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ8wwLcgMfkA4croVDOpswK2tZprJn9KSbbIHh2Gr-UB2-vDsdCeBrwCW7iLGQ7nZb7j0NYilkOcnmWp--iCVvearopc9foVxHlSWKfI2f-qdxO_23Au9OT23RU"
+ },
+ "11": 1
+ }],
+ "16": "\u003cCAHqB\u003dtALwqNpROdYci_Y4TBn0LjmW1rBmPoNbzZaw19XhS4KWQ@mail.gmail.com\u003e",
+ "18": "1587980211089",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.8715575
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980211089",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171baff1391825db"
+ }, {
+ "1": "msg-f:1665118117266291066",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980382357",
+ "10": "Le 27.04.2020 11:35, Elon a \u00e9crit : Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \"Focal Fossa\") resulting in substantial set of",
+ "11": ["^all", "^i", "^iim", "^io_im", "^io_imc4", "^io_lr", "^o", "^p_ag", "^smartlabel_personal", "^sq_ig_i_personal"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665118117266291066\u0026th\u003d171bb01b00b9797a\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ85qfZj_5W8qZRVH3TxgjyRXUBAUciVuaCNkWTdCniu4ewLp5msytruk5_uedlSyXoxABfFy1p4rh9HtKNdU56c-7hwb-yv4wwZBbu9meSF2IEPTWiVX8rEzkA"
+ },
+ "11": 1
+ }],
+ "16": "\u003cCAHqB\u003dtALwqNpROdYci_Y4TBn0LjmW1rBmPoNbzZaw19XhS4KWQ@mail.gmail.com\u003e",
+ "18": "1587980382219",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.88262963
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980382219",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171bb01b00b9797a"
+ }],
+ "8": "1587980130389",
+ "14": 0.88262963,
+ "15": {
+ "1": [{
+ "1": "",
+ "2": "billg@gmail.com"
+ }, {
+ "1": "",
+ "2": "jeffb@gmail.com"
+ }, {
+ "1": "",
+ "2": "larrye@gmail.com"
+ }, {
+ "1": "",
+ "2": "larryp@gmail.com"
+ }],
+ "2": [{
+ "1": "",
+ "2": "sergeyb@gmail.com"
+ }, {
+ "1": "",
+ "2": "markz@gmail.com"
+ }]
+ },
+ "17": 0,
+ "19": 1,
+ "20": "171baf6611169bff"
+ },
+ "7": "2",
+ "11": 1,
+ "13": "1587980382219"
+ }],
+ "2": "itemlist-ViewType(SECTIONED_INBOX_PRIMARY)-0",
+ "3": 3,
+ "4": 1,
+ "5": 0,
+ "6": [{
+ "1": "^io_lr"
+ }, {
+ "1": "^io_imc4"
+ }, {
+ "1": "^a"
+ }, {
+ "1": "^iim"
+ }, {
+ "1": "^os"
+ }, {
+ "1": "^sq_ig_i_personal"
+ }, {
+ "1": "^f"
+ }, {
+ "1": "^g"
+ }, {
+ "1": "^k"
+ }, {
+ "1": "^hapctl"
+ }, {
+ "1": "^t_e"
+ }, {
+ "1": "^o"
+ }, {
+ "1": "^p_ag"
+ }, {
+ "1": "^s"
+ }, {
+ "1": "^t"
+ }, {
+ "1": "^u"
+ }, {
+ "1": "^t_r_e"
+ }, {
+ "1": "^smartlabel_personal"
+ }, {
+ "1": "^apc"
+ }, {
+ "1": "^tl_b"
+ }, {
+ "1": "^io_im"
+ }, {
+ "1": "^io_imc3"
+ }, {
+ "1": "^io_unim"
+ }, {
+ "1": "^t_r"
+ }, {
+ "1": "^excl"
+ }, {
+ "1": "^t_p"
+ }, {
+ "1": "^io_re"
+ }, {
+ "1": "^all"
+ }, {
+ "1": "^f_bt"
+ }, {
+ "1": "^ss_sy"
+ }, {
+ "1": "^unei"
+ }],
+ "7": {
+ "1": 1,
+ "2": 67
+ },
+ "8": [{
+ "1": "^io_lr"
+ }, {
+ "1": "^io_imc4"
+ }, {
+ "1": "^a"
+ }, {
+ "1": "^iim"
+ }, {
+ "1": "^os"
+ }, {
+ "1": "^sq_ig_i_personal"
+ }, {
+ "1": "^f"
+ }, {
+ "1": "^g"
+ }, {
+ "1": "^i"
+ }, {
+ "1": "^k"
+ }, {
+ "1": "^hapctl"
+ }, {
+ "1": "^t_e"
+ }, {
+ "1": "^o"
+ }, {
+ "1": "^p_ag"
+ }, {
+ "1": "^s"
+ }, {
+ "1": "^t"
+ }, {
+ "1": "^u"
+ }, {
+ "1": "^t_r_e"
+ }, {
+ "1": "^smartlabel_personal"
+ }, {
+ "1": "^apc"
+ }, {
+ "1": "^tl_b"
+ }, {
+ "1": "^io_im"
+ }, {
+ "1": "^io_imc3"
+ }, {
+ "1": "^io_unim"
+ }, {
+ "1": "^t_r"
+ }, {
+ "1": "^excl"
+ }, {
+ "1": "^t_p"
+ }, {
+ "1": "^io_re"
+ }, {
+ "1": "^all"
+ }, {
+ "1": "^f_bt"
+ }, {
+ "1": "^ss_sy"
+ }, {
+ "1": "^unei"
+ }],
+ "14": 49,
+ "15": 0,
+ "16": "37473",
+ "18": 0
+ }
+}
\ No newline at end of file
diff --git a/test/testdata-parser-json/testdata-parser-bv-request-payload.json b/test/testdata-parser-json/testdata-parser-bv-request-payload.json
new file mode 100644
index 00000000..a9f55fb8
--- /dev/null
+++ b/test/testdata-parser-json/testdata-parser-bv-request-payload.json
@@ -0,0 +1,868 @@
+{
+ "1": 0,
+ "2": [{
+ "1": {
+ "1": "^all",
+ "2": "^all",
+ "7": 1,
+ "18": 5,
+ "21": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^b",
+ "2": "^b",
+ "7": 1,
+ "18": 5,
+ "21": 1,
+ "24": 1,
+ "25": 1
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^f",
+ "2": "^f",
+ "7": 1,
+ "18": 5,
+ "24": 1,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^i",
+ "2": "^i",
+ "7": 1,
+ "18": 5,
+ "24": 0,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^io_im",
+ "2": "^io_im",
+ "7": 1,
+ "18": 5,
+ "21": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^io_unim",
+ "2": "^io_unim",
+ "7": 1,
+ "12": 1000.0,
+ "13": 1,
+ "18": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^k",
+ "2": "^k",
+ "7": 1,
+ "18": 5,
+ "21": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^r",
+ "2": "^r",
+ "7": 1,
+ "18": 5,
+ "24": 1,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^s",
+ "2": "^s",
+ "7": 1,
+ "18": 5,
+ "21": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^scheduled",
+ "2": "^scheduled",
+ "7": 1,
+ "18": 5,
+ "21": 3,
+ "24": 1,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^smartlabel_finance",
+ "2": "^smartlabel_finance",
+ "7": 0,
+ "12": 1500.0,
+ "13": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^smartlabel_group",
+ "2": "^smartlabel_group",
+ "7": 1,
+ "12": 1200.0,
+ "13": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^smartlabel_notification",
+ "2": "^smartlabel_notification",
+ "7": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "374"
+ }, {
+ "1": {
+ "1": "^smartlabel_promo",
+ "2": "^smartlabel_promo",
+ "7": 0,
+ "12": 1100.0,
+ "13": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^smartlabel_receipt",
+ "2": "^smartlabel_receipt",
+ "7": 0,
+ "12": 1600.0,
+ "13": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^smartlabel_social",
+ "2": "^smartlabel_social",
+ "7": 0,
+ "12": 1400.0,
+ "13": 1,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^smartlabel_travel",
+ "2": "^smartlabel_travel",
+ "7": 0,
+ "12": 1700.0,
+ "13": 0,
+ "18": 1,
+ "21": 1,
+ "22": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1098"
+ }, {
+ "1": {
+ "1": "^t",
+ "2": "^t",
+ "7": 1,
+ "18": 5,
+ "24": 1,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^t_z",
+ "2": "^t_z",
+ "7": 1,
+ "18": 5,
+ "24": 1,
+ "25": 0
+ },
+ "2": "7"
+ }, {
+ "1": {
+ "1": "^x_1",
+ "2": "larryp/L",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1305"
+ }, {
+ "1": {
+ "1": "^x_2",
+ "2": "larryp",
+ "7": 1,
+ "12": 10000.0,
+ "13": 0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "23": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "32542"
+ }, {
+ "1": {
+ "1": "^x_3",
+ "2": "larryp/Ma",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1480"
+ }, {
+ "1": {
+ "1": "^x_4",
+ "2": "larryp/Draft",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1553"
+ }, {
+ "1": {
+ "1": "^x_4769357452883140367",
+ "2": "Mate",
+ "7": 1,
+ "9": [5],
+ "12": 10000.0,
+ "13": 1,
+ "18": 2,
+ "22": 2,
+ "23": 1,
+ "24": 1,
+ "25": 0
+ },
+ "2": "14917"
+ }, {
+ "1": {
+ "1": "^x_4781258247371085369",
+ "2": "_x_mate_label_",
+ "7": 1,
+ "9": [5],
+ "12": 10000.0,
+ "13": 1,
+ "18": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "21023"
+ }, {
+ "1": {
+ "1": "^x_5",
+ "2": "larryp/Delete",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "1599"
+ }, {
+ "1": {
+ "1": "^x_6",
+ "2": "larryp/Sents",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "2340"
+ }, {
+ "1": {
+ "1": "^x_7",
+ "2": "larryp/Spam",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "11137"
+ }, {
+ "1": {
+ "1": "^x_7226947756122782844",
+ "2": "Ops/1",
+ "7": 1,
+ "9": [5],
+ "12": 10000.0,
+ "13": 1,
+ "18": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "14431"
+ }, {
+ "1": {
+ "1": "^x_8",
+ "2": "larryp/personal",
+ "7": 1,
+ "12": 10000.0,
+ "18": 2,
+ "21": 2,
+ "22": 2,
+ "24": 1,
+ "25": 0
+ },
+ "2": "11590"
+ }],
+ "3": [{
+ "1": {
+ "1": "Working from home: The future of business is remote",
+ "2": "Le 27.04.2020 11:41, Elon a \u00e9crit : Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/ Sure",
+ "3": "1587980506989",
+ "4": "thread-a:r873907427374440696",
+ "5": [{
+ "1": "msg-a:r-5459297729901660292",
+ "2": {
+ "1": 1,
+ "2": "elonm@gmail.com",
+ "3": "Elon"
+ },
+ "7": "1587980506989",
+ "10": "Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/",
+ "11": ["^a", "^all", "^f", "^f_bt"],
+ "12": [{
+ "1": "text/plain",
+ "2": "work.txt",
+ "3": "278",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-a:r-5459297729901660292\u0026th\u003d171bb0399636172e\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "55fc38f1_52e78411_3774f559_d670a76b_62b66717",
+ "9": "ANGjdJ-DOb60xtgm3JunAO_2D0UjcMxbipwW9SOE7Exo_2E2Ms-RbxGYDn7IZDn24p-r8J_2JI3bmH3HEx12CNBZW8LXUbTtZ7elLSMMIg1wSaFCOFzxlN0haSlg6TU"
+ },
+ "11": 1
+ }],
+ "18": "1587980507491",
+ "30": {
+ "7": {
+ "1": "21660258"
+ },
+ "8": [21660258],
+ "10": 1
+ },
+ "31": "1587980507491",
+ "44": 0,
+ "56": "171bb0399636172e"
+ }, {
+ "1": "msg-f:1665118316230599953",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980572051",
+ "10": "Le 27.04.2020 11:41, Elon a \u00e9crit : Look at that : https://www.zdnet.com/topic/working-from-home-the-future-of-business-is-remote/ Sure",
+ "11": ["^all", "^i", "^iim", "^io_im", "^p_ag", "^smartlabel_personal", "^sq_ig_i_personal", "^u"],
+ "12": [{
+ "1": "text/plain",
+ "2": "work.txt",
+ "3": "278",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665118316230599953\u0026th\u003d171bb04953ebe511\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "55fc38f1_52e78411_3774f559_d670a76b_62b66717",
+ "9": "ANGjdJ_bYkjr-B2dxsuHDs7eqigtQqyPcYjUbdYFRHbRVQaC5gAaBwRSGi_LGvKCH2Jf_e1WHLFkGkvefNqhE2BgJdpGTTLVpdCaSjcDOmqWeT2IbMJFPL0BOymxF9s"
+ },
+ "11": 1
+ }],
+ "13": {
+ "28": "msg-f:1665118316230599953",
+ "31": [{
+ "1": {
+ "1": 0,
+ "2": "article"
+ },
+ "2": {
+ "1": [{
+ "1": "https://ci3.googleusercontent.com/proxy/VjhEslX1v9LhdeKFxo3OZLW5makCxJR8mPRerkuZJe2IcflH9QQCysUGsePSYVO1hCU1SCcKFOOi1hq8CLn_BO5v7JDU2OjTjjXhp2a7ihDEios1E3XZesuiJffUZ7T9FxF3fnLM6xxxoUsIGJceYzD3jXi4kDpZht7CblaTGl-7WuKx2MG5aAOi8f7rJbs7PekUWgfLW3Lb2qJrRBVQtSAU8rXu560SVET-a9d4Vi5HHJIhcgBAYoTL9Q",
+ "7": 1,
+ "11": 1
+ }],
+ "2": {
+ "1": [{
+ "1": "Working from home: The future of business is remote | ZDNet"
+ }]
+ },
+ "3": [{
+ "1": [{
+ "1": "www.zdnet.com"
+ }]
+ }]
+ },
+ "4": "5152721027681343705",
+ "5": {
+ "1": "4503599627370495"
+ },
+ "6": 1
+ }]
+ },
+ "16": "\u003cCAHqB\u003dtDjJtq9QsjipXxqx4UE07nmSkDib1XqH0Wi0R7JU8vEmg@mail.gmail.com\u003e",
+ "18": "1587980571966",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.87796235
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980571966",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171bb04953ebe511"
+ }],
+ "8": "1587980507468",
+ "14": 0.87796235,
+ "15": {
+ "1": [{
+ "1": "",
+ "2": "billg@gmail.com"
+ }, {
+ "1": "",
+ "2": "jeffb@gmail.com"
+ }, {
+ "1": "",
+ "2": "larrye@gmail.com"
+ }, {
+ "1": "",
+ "2": "larryp@gmail.com"
+ }],
+ "2": [{
+ "1": "",
+ "2": "sergeyb@gmail.com"
+ }, {
+ "1": "",
+ "2": "markz@gmail.com"
+ }]
+ },
+ "17": 0,
+ "19": 1,
+ "20": "171bb02371f0da52"
+ },
+ "2": "37370"
+ }, {
+ "1": {
+ "1": "Ubuntu 20.04 Download Link \u0026 New Features (Updated)",
+ "2": "Le 27.04.2020 11:35, Elon a \u00e9crit : Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \"Focal Fossa\") resulting in substantial set of",
+ "3": "1587980129841",
+ "4": "thread-a:r-7005674805299871901",
+ "5": [{
+ "1": "msg-a:r-7004022322083187773",
+ "2": {
+ "1": 1,
+ "2": "elonm@gmail.com",
+ "3": "Elon"
+ },
+ "7": "1587980129841",
+ "10": "Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \u201cFocal Fossa\u201d) resulting in substantial set of improvements that improve just about every part of the",
+ "11": ["^a", "^all", "^f", "^f_bt", "^io_lr", "^o"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-a:r-7004022322083187773\u0026th\u003d171bafdd8d3f48bb\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ9XVTKyfkpZNRqOs8f4k5NRjCJkuLVsyMLBTDR4BsawsuttWYtJuC81rtPH7I1W_DUFP5ptsbmfALldSc7W-stvYozo3T2ptqnEHPsKnJAVdWRRHak6v6ieoEQ"
+ },
+ "11": 1
+ }],
+ "18": "1587980130515",
+ "30": {
+ "7": {
+ "1": "21660258"
+ },
+ "8": [21660258],
+ "10": 1
+ },
+ "31": "1587980130515",
+ "44": 0,
+ "56": "171bafdd8d3f48bb"
+ }, {
+ "1": "msg-f:1665117937823393243",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980211022",
+ "10": "Le 27.04.2020 11:35, Elon a \u00e9crit : Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \"Focal Fossa\") resulting in substantial set of",
+ "11": ["^all", "^io_im", "^io_lr", "^k", "^o", "^smartlabel_personal"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665117937823393243\u0026th\u003d171baff1391825db\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ_xZ8LqN1JzTjBLMc9WKn2DcS_XIDVklzsRq-fWWCcNIUamspT1g-MxpScR_ATRv4h88ZZAGt0Mb4ihSoQemITBKWvwbvrE5IdlHeC1iimNwoCWGsH6TLytW1w"
+ },
+ "11": 1
+ }],
+ "16": "\u003cCAHqB\u003dtALwqNpROdYci_Y4TBn0LjmW1rBmPoNbzZaw19XhS4KWQ@mail.gmail.com\u003e",
+ "18": "1587980211089",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.8715575
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980211089",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171baff1391825db"
+ }, {
+ "1": "msg-f:1665118117266291066",
+ "2": {
+ "1": 1,
+ "2": "Eric@gmail.com",
+ "3": "Eric"
+ },
+ "7": "1587980382357",
+ "10": "Le 27.04.2020 11:35, Elon a \u00e9crit : Six months of blood, sweat and development tears have gone in Ubuntu 20.04 LTS (which is codenamed \"Focal Fossa\") resulting in substantial set of",
+ "11": ["^all", "^i", "^iim", "^io_im", "^io_imc4", "^io_lr", "^o", "^p_ag", "^smartlabel_personal", "^sq_ig_i_personal"],
+ "12": [{
+ "1": "text/plain",
+ "2": "Ubuntu_20.04.txt",
+ "3": "1017",
+ "4": "0.1",
+ "6": "https://mail.google.com/mail/?ui\u003d2\u0026ik\u003d74384930e0\u0026attid\u003d0.1\u0026permmsgid\u003dmsg-f:1665118117266291066\u0026th\u003d171bb01b00b9797a\u0026view\u003datt\u0026zw",
+ "7": 0,
+ "8": {
+ "3": "54877efe_63d780ef_926e7c91_2aa63925_d44a83c1",
+ "9": "ANGjdJ-XmyLBjpqpWpjoQgJ7TgvtSTe3BdW_e6sIElgjggNFBxiuImj9HNeeNpw342X7tbUCyY8DoJFSUasTZcJeOOutiVdW1mwtApYWziF1PIShGLsE7qtr95UpBpc"
+ },
+ "11": 1
+ }],
+ "16": "\u003cCAHqB\u003dtALwqNpROdYci_Y4TBn0LjmW1rBmPoNbzZaw19XhS4KWQ@mail.gmail.com\u003e",
+ "18": "1587980382219",
+ "30": {
+ "4": {
+ "1": 1
+ },
+ "5": {
+ "1": 0.88262963
+ },
+ "7": {
+ "1": "21660255"
+ },
+ "8": [21660255, 40510207, 21660332, 40510093, 40510189, 40510198],
+ "10": 1
+ },
+ "31": "1587980382219",
+ "44": 0,
+ "45": {
+ "3": 1
+ },
+ "56": "171bb01b00b9797a"
+ }],
+ "8": "1587980130389",
+ "14": 0.88262963,
+ "15": {
+ "1": [{
+ "1": "",
+ "2": "billg@gmail.com"
+ }, {
+ "1": "",
+ "2": "jeffb@gmail.com"
+ }, {
+ "1": "",
+ "2": "larrye@gmail.com"
+ }, {
+ "1": "",
+ "2": "larryp@gmail.com"
+ }],
+ "2": [{
+ "1": "",
+ "2": "sergeyb@gmail.com"
+ }, {
+ "1": "",
+ "2": "markz@gmail.com"
+ }]
+ },
+ "17": 0,
+ "19": 1,
+ "20": "171baf6611169bff"
+ },
+ "2": "37360"
+ }],
+ "4": 1,
+ "5": "37377",
+ "6": 1,
+ "7": {
+ "1": [{
+ "1": "^smartlabel_notification",
+ "2": 1,
+ "3": 1
+ }, {
+ "1": "^iim",
+ "2": 10,
+ "3": 27
+ }, {
+ "1": "^smartlabel_group",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^b",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^x_4769357452883140367",
+ "2": 0,
+ "3": 3
+ }, {
+ "1": "^sq_ig_i_personal",
+ "2": 15,
+ "3": 80,
+ "4": 0
+ }, {
+ "1": "^sq_ig_i_social",
+ "2": 0,
+ "3": 0,
+ "4": 0
+ }, {
+ "1": "^f",
+ "2": 0,
+ "3": 394
+ }, {
+ "1": "^i",
+ "2": 19,
+ "3": 84
+ }, {
+ "1": "^cr",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^p_cc",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^io_f_iiim",
+ "2": 19,
+ "3": 84
+ }, {
+ "1": "^k",
+ "2": 1,
+ "3": 19
+ }, {
+ "1": "^sq_ig_i_promo",
+ "2": 3,
+ "3": 3,
+ "4": 0
+ }, {
+ "1": "^io_f_iim",
+ "2": 10,
+ "3": 27
+ }, {
+ "1": "^smartlabel_pure_notif",
+ "2": 1,
+ "3": 1
+ }, {
+ "1": "^smartlabel_finance",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^smartlabel_promo",
+ "2": 3,
+ "3": 3
+ }, {
+ "1": "^x_7226947756122782844",
+ "2": 0,
+ "3": 7
+ }, {
+ "1": "^r",
+ "2": 0,
+ "3": 4
+ }, {
+ "1": "^s",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^t",
+ "2": 0,
+ "3": 3
+ }, {
+ "1": "^io_im",
+ "2": 10,
+ "3": 28
+ }, {
+ "1": "^sq_ig_i_group",
+ "2": 0,
+ "3": 0,
+ "4": 0
+ }, {
+ "1": "^x_1",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^x_2",
+ "2": 4,
+ "3": 605
+ }, {
+ "1": "^x_3",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^x_4",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^scheduled",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^smartlabel_social",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^all",
+ "2": 23,
+ "3": 874
+ }, {
+ "1": "^sq_ig_i_notification",
+ "2": 1,
+ "3": 1,
+ "4": 0
+ }, {
+ "1": "^assistive_travel",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^assistive_purchase",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^io_f_ti",
+ "2": 0,
+ "3": 3
+ }, {
+ "1": "^x_5",
+ "2": 1,
+ "3": 5
+ }, {
+ "1": "^t_z",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^x_6",
+ "2": 0,
+ "3": 553
+ }, {
+ "1": "^smartlabel_travel",
+ "2": 0,
+ "3": 0
+ }, {
+ "1": "^x_7",
+ "2": 3,
+ "3": 5
+ }, {
+ "1": "^x_4781258247371085369",
+ "2": 0,
+ "3": 1
+ }, {
+ "1": "^x_8",
+ "2": 0,
+ "3": 43
+ }]
+ },
+ "12": {
+ "1": 1,
+ "2": 93
+ },
+ "19": {
+ "1": "37377"
+ }
+}
\ No newline at end of file
diff --git a/test/testdata-parser-json/testdata-parser-fd-embedded.json b/test/testdata-parser-json/testdata-parser-fd-embedded.json
new file mode 100644
index 00000000..73656b7b
--- /dev/null
+++ b/test/testdata-parser-json/testdata-parser-fd-embedded.json
@@ -0,0 +1,1113 @@
+[
+ null,
+ [
+ [
+ 0,
+ [
+ "Test email 4",
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ 1663052536832,
+ "thread-f:1743836977043622489|msg-f:1743836977043622489",
+ [
+ [
+ "msg-f:1743836977043622489",
+ [
+ 1,
+ "jostein@secure.kjonigsen.net",
+ "Jostein Kjønigsen"
+ ],
+ [
+ [
+ 1,
+ "jostein@gmail.com",
+ "Jostein Kjønigsen"
+ ]
+ ],
+ null,
+ null,
+ [
+ [
+ 1,
+ "jostein@kjonigsen.net"
+ ]
+ ],
+ 1663052536832,
+ "Test email 4",
+ [
+ null,
+ [
+ [
+ 0,
+ null,
+ [
+ null,
+ "\r\n \r\n\r\n \r\n \r\n \r\n\r\n"
+ ],
+ -242693187
+ ]
+ ],
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0
+ ],
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ [
+ "^all",
+ "^i",
+ "^io_unim",
+ "^smartlabel_personal",
+ "^sq_ig_i_personal",
+ "^u"
+ ],
+ [
+ [
+ "application/ics",
+ "invite.ics",
+ 1564,
+ "0.0.2",
+ "",
+ "https://mail.google.com/mail/?ui=0&ik=99e3eb73b5&attid=0.0.2&permmsgid=msg-f:1743836977043622489&th=18335a7f90a24d19&view=att&zw",
+ 0,
+ [
+ "/gmail/att/230514602909/AAXoEvt4U0y0XpJwLAslJg.4/38185",
+ 1564,
+ "1609a18c_13e23b8d_7e0af756_3c5df6a4_2e2c506b",
+ 1064196813,
+ 1564,
+ 1,
+ null,
+ null,
+ "ANGjdJ8dTFofalDEbii384u_Y-_YhwxHS-DyVo8nOiTqVNAf7j4eW9f0o8lAgbZHVX5QhKCpEh8k2y_oEm4XnusbV3FlcBy99xY1v7ulwo3g9CbVzB3z9ULc07yNyNE",
+ null,
+ null,
+ null,
+ null,
+ "YjM1YmI0OTQ4ZjI3MmU5ZDg5ZTBjZDk1NjM2ZDRhNGUxZGIzYmZmZjFmNWY1ZDJmZTk0OTg2NWQzNmE1NTVhYQ=="
+ ],
+ null,
+ null,
+ 0
+ ]
+ ],
+ null,
+ "<491e0008-2936-f0e2-171a-3d696268b5b7@secure.kjonigsen.net>",
+ null,
+ null,
+ null,
+ 1663052537006,
+ [
+ 0,
+ 1,
+ "",
+ -1,
+ null,
+ null,
+ null,
+ "secure.kjonigsen.net",
+ "secure.kjonigsen.net",
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "jostein@secure.kjonigsen.net",
+ 1
+ ],
+ null,
+ null,
+ [
+ 1,
+ "jostein@gmail.com"
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ [
+ null,
+ null,
+ null,
+ [
+ 1
+ ],
+ [
+ 0.5484427
+ ],
+ null,
+ [
+ 21660393
+ ],
+ [
+ 40510810,
+ 21660393,
+ 40510639,
+ 40510624,
+ 40510407,
+ 40510631,
+ 40510372,
+ 40510644,
+ 40510805
+ ],
+ null,
+ 1
+ ],
+ 1663052537006,
+ null,
+ null,
+ 2,
+ null,
+ [
+ null,
+ null,
+ null,
+ null,
+ 2
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ [
+ null,
+ null,
+ 1
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "18335a7dcae04a59"
+ ]
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0.5484427,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ "18335a7dcae04a59"
+ ],
+ 0,
+ 0,
+ [
+ [
+ "^io_unim"
+ ],
+ [
+ "^s"
+ ],
+ [
+ "^sq_ig_i_personal"
+ ],
+ [
+ "^u"
+ ],
+ [
+ "^g"
+ ],
+ [
+ "^smartlabel_personal"
+ ],
+ [
+ "^i"
+ ],
+ [
+ "^k"
+ ],
+ [
+ "^all"
+ ]
+ ]
+ ],
+ [
+ 0,
+ [
+ "Test email 2",
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ 1663052308262,
+ "thread-f:1743836737294347280|msg-f:1743836737294347280",
+ [
+ [
+ "msg-f:1743836737294347280",
+ [
+ 1,
+ "jostein@secure.kjonigsen.net",
+ "Jostein Kjønigsen"
+ ],
+ [
+ [
+ 1,
+ "jostein@gmail.com",
+ "Jostein Kjønigsen"
+ ]
+ ],
+ null,
+ null,
+ [
+ [
+ 1,
+ "jostein@kjonigsen.net"
+ ]
+ ],
+ 1663052308262,
+ "Test email 2",
+ [
+ null,
+ [
+ [
+ 0,
+ null,
+ [
+ null,
+ "\r\n \r\n\r\n \r\n \r\n \r\n\r\n"
+ ],
+ 1026127672
+ ]
+ ],
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0
+ ],
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ [
+ "^all",
+ "^i",
+ "^io_unim",
+ "^smartlabel_personal",
+ "^sq_ig_i_personal",
+ "^u"
+ ],
+ null,
+ null,
+ "<9d55b92d-51e4-6400-28ac-046c4c6c1e95@secure.kjonigsen.net>",
+ null,
+ null,
+ null,
+ 1663052308363,
+ [
+ 0,
+ 1,
+ "",
+ -1,
+ null,
+ null,
+ null,
+ "secure.kjonigsen.net",
+ "secure.kjonigsen.net",
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "jostein@secure.kjonigsen.net",
+ 1
+ ],
+ null,
+ null,
+ [
+ 1,
+ "jostein@gmail.com"
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ [
+ null,
+ null,
+ null,
+ [
+ 1
+ ],
+ [
+ 0.6030153
+ ],
+ null,
+ [
+ 21660393
+ ],
+ [
+ 40510810,
+ 21660393,
+ 40510639,
+ 40510624,
+ 40510407,
+ 40510631,
+ 40510372,
+ 40510644,
+ 40510805
+ ],
+ null,
+ 1
+ ],
+ 1663052308363,
+ null,
+ null,
+ 2,
+ null,
+ [
+ null,
+ null,
+ null,
+ null,
+ 2
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ [
+ null,
+ null,
+ 1
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "18335a45f8b4ac10"
+ ]
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0.6030153,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ "18335a45f8b4ac10"
+ ],
+ 0,
+ 0,
+ [
+ [
+ "^io_unim"
+ ],
+ [
+ "^s"
+ ],
+ [
+ "^sq_ig_i_personal"
+ ],
+ [
+ "^u"
+ ],
+ [
+ "^g"
+ ],
+ [
+ "^smartlabel_personal"
+ ],
+ [
+ "^i"
+ ],
+ [
+ "^k"
+ ],
+ [
+ "^all"
+ ]
+ ]
+ ],
+ [
+ 0,
+ [
+ "Test email 3",
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ 1663052315077,
+ "thread-f:1743836743950419315|msg-f:1743836743950419315",
+ [
+ [
+ "msg-f:1743836743950419315",
+ [
+ 1,
+ "jostein@secure.kjonigsen.net",
+ "Jostein Kjønigsen"
+ ],
+ [
+ [
+ 1,
+ "jostein@gmail.com",
+ "Jostein Kjønigsen"
+ ]
+ ],
+ null,
+ null,
+ [
+ [
+ 1,
+ "jostein@kjonigsen.net"
+ ]
+ ],
+ 1663052315077,
+ "Test email 3",
+ [
+ null,
+ [
+ [
+ 0,
+ null,
+ [
+ null,
+ "\r\n \r\n\r\n \r\n \r\n \r\n\r\n"
+ ],
+ 924929475
+ ]
+ ],
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0
+ ],
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ [
+ "^all",
+ "^i",
+ "^io_lr",
+ "^io_unim",
+ "^o",
+ "^smartlabel_personal",
+ "^sq_ig_i_personal"
+ ],
+ null,
+ null,
+ "<4c8d3143-b98b-5f5f-152b-23a9967205b7@secure.kjonigsen.net>",
+ null,
+ null,
+ null,
+ 1663052314711,
+ [
+ 0,
+ 1,
+ "",
+ -1,
+ null,
+ null,
+ null,
+ "secure.kjonigsen.net",
+ "secure.kjonigsen.net",
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "jostein@secure.kjonigsen.net",
+ 1
+ ],
+ null,
+ null,
+ [
+ 1,
+ "jostein@gmail.com"
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ [
+ null,
+ null,
+ null,
+ [
+ 1
+ ],
+ [
+ 0.59927684
+ ],
+ null,
+ [
+ 21660393
+ ],
+ [
+ 40510810,
+ 21660393,
+ 40510639,
+ 40510624,
+ 40510407,
+ 40510631,
+ 40510372,
+ 40510644,
+ 40510805
+ ],
+ null,
+ 1
+ ],
+ 1663052314711,
+ null,
+ null,
+ 2,
+ null,
+ [
+ null,
+ null,
+ null,
+ null,
+ 2
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ [
+ null,
+ null,
+ 1
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "18335a4785704573"
+ ]
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0.59927684,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ "18335a4785704573"
+ ],
+ 0,
+ 0,
+ [
+ [
+ "^io_unim"
+ ],
+ [
+ "^o"
+ ],
+ [
+ "^io_lr"
+ ],
+ [
+ "^s"
+ ],
+ [
+ "^sq_ig_i_personal"
+ ],
+ [
+ "^g"
+ ],
+ [
+ "^smartlabel_personal"
+ ],
+ [
+ "^i"
+ ],
+ [
+ "^k"
+ ],
+ [
+ "^all"
+ ]
+ ]
+ ],
+ [
+ 0,
+ [
+ "Test email 6",
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ 1663052544509,
+ "thread-f:1743836984656416025|msg-f:1743836984656416025",
+ [
+ [
+ "msg-f:1743836984656416025",
+ [
+ 1,
+ "jostein@secure.kjonigsen.net",
+ "Jostein Kjønigsen"
+ ],
+ [
+ [
+ 1,
+ "jostein@gmail.com",
+ "Jostein Kjønigsen"
+ ]
+ ],
+ null,
+ null,
+ [
+ [
+ 1,
+ "jostein@kjonigsen.net"
+ ]
+ ],
+ 1663052544509,
+ "Test email 6",
+ [
+ null,
+ [
+ [
+ 0,
+ null,
+ [
+ null,
+ "\r\n \r\n\r\n \r\n \r\n \r\n\r\n"
+ ],
+ 101876595
+ ]
+ ],
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0
+ ],
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ [
+ "^all",
+ "^i",
+ "^io_unim",
+ "^smartlabel_personal",
+ "^sq_ig_i_personal",
+ "^u"
+ ],
+ null,
+ null,
+ "<4f056d85-c2ae-6021-e94a-f0d4b8a2b0a5@secure.kjonigsen.net>",
+ null,
+ null,
+ null,
+ 1663052544266,
+ [
+ 0,
+ 1,
+ "",
+ -1,
+ null,
+ null,
+ null,
+ "secure.kjonigsen.net",
+ "secure.kjonigsen.net",
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "jostein@secure.kjonigsen.net",
+ 1
+ ],
+ null,
+ null,
+ [
+ 1,
+ "jostein@gmail.com"
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ [
+ null,
+ null,
+ null,
+ [
+ 1
+ ],
+ [
+ 0.5299874
+ ],
+ null,
+ [
+ 21660393
+ ],
+ [
+ 40510810,
+ 21660393,
+ 40510639,
+ 40510624,
+ 40510407,
+ 40510631,
+ 40510372,
+ 40510644,
+ 40510805
+ ],
+ null,
+ 1
+ ],
+ 1663052544266,
+ null,
+ null,
+ 2,
+ null,
+ [
+ null,
+ null,
+ null,
+ null,
+ 2
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ [
+ null,
+ null,
+ 1
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "18335a7f90a24d19"
+ ]
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0.5299874,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ "18335a7f90a24d19"
+ ],
+ 0,
+ 0,
+ [
+ [
+ "^io_unim"
+ ],
+ [
+ "^s"
+ ],
+ [
+ "^sq_ig_i_personal"
+ ],
+ [
+ "^u"
+ ],
+ [
+ "^g"
+ ],
+ [
+ "^smartlabel_personal"
+ ],
+ [
+ "^i"
+ ],
+ [
+ "^k"
+ ],
+ [
+ "^all"
+ ]
+ ]
+ ],
+ [
+ 0,
+ [
+ "Test email 1",
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ 1663052300221,
+ "thread-f:1743836728797845896|msg-f:1743836728797845896",
+ [
+ [
+ "msg-f:1743836728797845896",
+ [
+ 1,
+ "jostein@secure.kjonigsen.net",
+ "Jostein Kjønigsen"
+ ],
+ [
+ [
+ 1,
+ "jostein@gmail.com",
+ "Jostein Kjønigsen"
+ ]
+ ],
+ null,
+ null,
+ [
+ [
+ 1,
+ "jostein@kjonigsen.net"
+ ]
+ ],
+ 1663052300221,
+ "Test email 1",
+ [
+ null,
+ [
+ [
+ 0,
+ null,
+ [
+ null,
+ "\r\n \r\n\r\n \r\n \r\n \r\n\r\n"
+ ],
+ -1448807196
+ ]
+ ],
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0
+ ],
+ "-- Vennlig hilsen Jostein Kjønigsen jostein@kjonigsen.net 🍵 jostein@gmail.com https://jostein.kjønigsen.no",
+ [
+ "^all",
+ "^i",
+ "^io_unim",
+ "^smartlabel_personal",
+ "^sq_ig_i_personal",
+ "^u"
+ ],
+ null,
+ null,
+ "",
+ null,
+ null,
+ null,
+ 1663052300260,
+ [
+ 0,
+ 1,
+ "",
+ -1,
+ null,
+ null,
+ null,
+ "secure.kjonigsen.net",
+ "secure.kjonigsen.net",
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "jostein@secure.kjonigsen.net",
+ 1
+ ],
+ null,
+ null,
+ [
+ 1,
+ "jostein@gmail.com"
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ [
+ null,
+ null,
+ null,
+ [
+ 1
+ ],
+ [
+ 0.59923285
+ ],
+ null,
+ [
+ 21660393
+ ],
+ [
+ 40510810,
+ 21660393,
+ 40510639,
+ 40510624,
+ 40510407,
+ 40510631,
+ 40510372,
+ 40510644,
+ 40510805
+ ],
+ null,
+ 1
+ ],
+ 1663052300260,
+ null,
+ null,
+ 2,
+ null,
+ [
+ null,
+ null,
+ null,
+ null,
+ 2
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ [
+ null,
+ null,
+ 1
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "18335a43fe465988"
+ ]
+ ],
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0.59923285,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ "18335a43fe465988"
+ ],
+ 0,
+ 0,
+ [
+ [
+ "^io_unim"
+ ],
+ [
+ "^s"
+ ],
+ [
+ "^sq_ig_i_personal"
+ ],
+ [
+ "^u"
+ ],
+ [
+ "^g"
+ ],
+ [
+ "^smartlabel_personal"
+ ],
+ [
+ "^i"
+ ],
+ [
+ "^k"
+ ],
+ [
+ "^all"
+ ]
+ ]
+ ]
+ ]
+]
diff --git a/test/testdata-parser-json/testdata-parser-fd-request.json b/test/testdata-parser-json/testdata-parser-fd-request.json
new file mode 100644
index 00000000..2c120ff3
--- /dev/null
+++ b/test/testdata-parser-json/testdata-parser-fd-request.json
@@ -0,0 +1,195 @@
+{
+ "1": 0,
+ "2": [
+ {
+ "1": "thread-a:r-4872725344334517560",
+ "2": {
+ "1": {
+ "1": "thread-a:r-4872725344334517560",
+ "2": "test subject",
+ "3": "",
+ "4": "1633120435728",
+ "13": 0,
+ "16": "17c3d9041ec7d0a5"
+ },
+ "2": [
+ {
+ "1": "msg-a:r-4871072856822866136",
+ "2": {
+ "1": 1,
+ "2": "user@gmail.com",
+ "3": "First Last"
+ },
+ "3": "1633120435728",
+ "4": [
+ "^all",
+ "^r",
+ "^r_bt"
+ ],
+ "7": "1633120436716",
+ "11": "",
+ "16": "1633120436716",
+ "22": 0,
+ "28": "17c3d9041ec7d0a5"
+ }
+ ]
+ },
+ "3": [
+ {
+ "1": "msg-a:r-4871072856822866136",
+ "2": {
+ "5": "test subject",
+ "6": {
+ "2": [
+ {
+ "1": 0,
+ "3": {
+ "2": "
\r\n"
+ },
+ "4": -297155691
+ }
+ ],
+ "3": 0,
+ "7": 1,
+ "8": 0
+ },
+ "7": "",
+ "8": "",
+ "11": {
+ "1": 0,
+ "2": 1,
+ "3": "",
+ "4": -1,
+ "8": "gmail.com",
+ "11": 0,
+ "17": "user@gmail.com",
+ "18": 1
+ },
+ "12": {
+ "1": 1,
+ "2": "user@gmail.com"
+ },
+ "17": "1633120436716",
+ "20": {
+ "6": 0
+ },
+ "21": {
+ "4": 0
+ },
+ "30": [
+ "en"
+ ],
+ "35": "17c3d9041ec7d0a5"
+ }
+ }
+ ],
+ "5": "6371890"
+ }, {
+ "1": "thread-a:r-4872725344334517560",
+ "2": {
+ "1": {
+ "1": "thread-a:r-4872725344334517560",
+ "2": "test subject",
+ "3": "aaa",
+ "4": "1633120642148",
+ "11": {
+ "1": [
+ {
+ "1": "First Last",
+ "2": "user@gmail.com"
+ }
+ ]
+ },
+ "13": 0,
+ "16": "17c3d9041ec7d0a5"
+ },
+ "2": [
+ {
+ "1": "msg-a:r-4871072856822866136",
+ "2": {
+ "1": 1,
+ "2": "user@gmail.com",
+ "3": "First Last"
+ },
+ "3": "1633120642148",
+ "4": [
+ "^all",
+ "^f",
+ "^f_bt",
+ "^f_cl",
+ "^i",
+ "^iim",
+ "^io_im",
+ "^io_imc3",
+ "^pfg",
+ "^sq_ig_i_personal",
+ "^u"
+ ],
+ "7": "1633120642270",
+ "11": "aaa",
+ "16": "1633120642270",
+ "22": 0,
+ "28": "17c3d9364dec527d"
+ }
+ ]
+ },
+ "3": [
+ {
+ "1": "msg-a:r-4871072856822866136",
+ "2": {
+ "1": [
+ {
+ "1": 1,
+ "2": "user@gmail.com",
+ "3": "First Last"
+ }
+ ],
+ "5": "test subject",
+ "6": {
+ "2": [
+ {
+ "1": 0,
+ "3": {
+ "2": "aaa
\r\n"
+ },
+ "4": 679037643
+ }
+ ],
+ "3": 0,
+ "7": 1,
+ "8": 0
+ },
+ "7": "aaa",
+ "8": "",
+ "11": {
+ "1": 0,
+ "2": 1,
+ "3": "",
+ "4": -1,
+ "8": "gmail.com",
+ "11": 0,
+ "17": "user@gmail.com",
+ "18": 1
+ },
+ "12": {
+ "1": 1,
+ "2": "user@gmail.com"
+ },
+ "17": "1633120642270",
+ "21": {
+ "1": 0
+ },
+ "30": [
+ "en"
+ ],
+ "35": "17c3d9364dec527d"
+ }
+ }
+ ],
+ "5": "6371997"
+ }
+ ],
+ "5": {
+ "1": "6371896"
+ }
+}
\ No newline at end of file
diff --git a/test/testdata-parser-json/testdata-parser-mla.json b/test/testdata-parser-json/testdata-parser-mla.json
new file mode 100644
index 00000000..5ad3b803
--- /dev/null
+++ b/test/testdata-parser-json/testdata-parser-mla.json
@@ -0,0 +1,33 @@
+[
+ "mla",
+ [
+ [
+ "user2@gsuite2.com",
+ 0,
+ 0,
+ 3,
+ "Gmail Dev"
+ ],
+ [
+ "primary@gmail.com",
+ 1,
+ 0,
+ 0,
+ "Primary One"
+ ],
+ [
+ "mamo.stefania@gmail.com",
+ 0,
+ 0,
+ 1,
+ "Стефанія Мамо"
+ ],
+ [
+ "Jack.Sparrow@gsuite1.net",
+ 0,
+ 0,
+ 2,
+ "Jack Sparrow"
+ ]
+ ]
+]
\ No newline at end of file
diff --git a/test/testdata-parser.js b/test/testdata-parser.js
index b63f84f5..0731c34b 100644
--- a/test/testdata-parser.js
+++ b/test/testdata-parser.js
@@ -31,6 +31,10 @@ var new_gmail_open_email_action_body_params = "{\"2\":{\"1\":[{\"1\":\"5\",\"2\"
var new_gmail_new_email_body_params = "{\"1\":\"thread-f:1613947906803228078\",\"2\":{\"7\":{\"2\":[\"^us\"],\"3\":[\"msg-f:1613947906803228078\"]}}}";
+var new_gmail_apply_label_action_body_params = "{\"2\":{\"1\":[{\"1\":\"6\",\"2\":{\"1\":\"thread-f:1644041322536515974|msg-f:1647596654245574633\",\"2\":{\"7\":{\"1\":[\"^x_7680127119979202084\"],\"3\":[\"msg-f:1647596654245574633\"]}}}},{\"1\":\"7\",\"2\":{\"1\":\"thread-f:1647490793383449487|msg-f:1647581105847759434\",\"2\":{\"7\":{\"1\":[\"^x_7680127119979202084\"],\"3\":[\"msg-f:1647581105847759434\"]}}}}]},\"3\":{\"1\":1,\"2\":\"760329\",\"5\":{\"2\":0},\"7\":1},\"4\":{\"2\":2,\"3\":\"1571307981227\",\"4\":0,\"5\":431},\"5\":2}";
+
+var new_gmail_sent_email_json = "{\"1\":\"msg-a:r1280593055912233690\",\"2\":{\"1\":1,\"2\":\"eric.karlsson1@gmail.com\",\"3\":\"Eric Karlsson1\"},\"3\":[{\"1\":1,\"2\":\"eric.karlsson2@gmail.com\",\"3\":\"Eric Karlsson2\"},{\"1\":1,\"2\":\"eric.karlsson3@gmail.com\"}],\"4\":[{\"1\":1,\"2\":\"eric.karlsson4@gmail.com\"},{\"1\":1,\"2\":\"eric.karlsson5@gmail.com\"}],\"5\":[{\"1\":1,\"2\":\"eric.karlsson6@gmail.com\",\"3\":\"Eric Karlsson6\"},{\"1\":1,\"2\":\"eric.karlsson7@gmail.com\",\"3\":\"Eric Karlsson7\"}],\"7\":\"1562634059674\",\"8\":\"Test Parse Sent\",\"9\":{\"2\":[{\"1\":0,\"2\":\"Test
Link <\/a>Test
<\/div>--
Thanks,
<\/font><\/div>Eric Karlsson<\/b><\/font><\/div>Product Development<\/font><\/div>+1 240.688.9219 <\/span><\/span><\/font><\/div>
<\/font><\/div>
<\/div><\/div><\/div><\/div><\/div><\/div><\/div><\/div>\"}],\"7\":1},\"11\":[\"^all\",\"^pfg\",\"^f_bt\",\"^f_btns\",\"^f_cl\",\"^a\"],\"12\":[{\"1\":\"image\/png\",\"2\":\"Socket Error.PNG\",\"3\":\"108256\",\"5\":\"f_jxv3xqgb1\",\"6\":\"https:\/\/mail.google.com\/mail\/?ui=2&ik=5a14ab333d&attid=0.1&permmsgid=msg-a:r1280593055912233690&view=att&realattid=f_jxv3xqgb1&zw\",\"7\":0,\"8\":{\"1\":\"\/gmail\/att\/166604492527\/AAWNNRTJX9IJ7ZaSARt87A.4\/1747\",\"2\":\"108256\",\"3\":\"bb9be3f3_feddda5b_ced3b555_987aef4d_a2be44fc\",\"4\":1934455450,\"5\":\"148142\",\"7\":\"b64magic:NK,f,76\",\"9\":\"ANGjdJ-QStOwYEIO1RZFXbrqEojK2WgFoZ0V1Kz3vpz9UOHjUgrZQgA1-rl7VZQpCNuUaHp9TybcxV3TnVJ1i_jXREotXNE89ubF0BiJZ7m9CzZjhz8POOrOBDoNS4A\"},\"10\":\"GkEvYmxvYnN0b3JlL3Byb2QvZ21haWwtdXBsb2FkLzliZDcwM2JhLTY4ZjQtNGU2ZC05MmU0LTMwYjRhNmQ5ZDYzYijgzQYyLGJiOWJlM2YzX2ZlZGRkYTViX2NlZDNiNTU1Xzk4N2FlZjRkX2EyYmU0NGZjOJrltZoHSK6FCVgDYhBiNjRtYWdpYzpOSyxmLDc2aACaAUAxYzdlNDY2ZjYzYTkyYjI3ZDU0NzliNzYxNzMwZmRhNDQ4OGExMjU1NDA2Mjg4YzZjYjQ5OTU5NmM1NDJiNjJmqgECCAE=\",\"11\":1},{\"1\":\"image\/jpeg\",\"2\":\"8002291_3.jpg\",\"3\":\"2312479\",\"5\":\"f_jxv3xqg00\",\"6\":\"https:\/\/mail.google.com\/mail\/?ui=2&ik=5a14ab333d&attid=0.2&permmsgid=msg-a:r1280593055912233690&view=att&realattid=f_jxv3xqg00&zw\",\"7\":0,\"8\":{\"1\":\"\/gmail\/att\/166604492527\/AAWNNRTJX9IJ7ZaSARt87A.4\/150129\",\"2\":\"2312479\",\"3\":\"96e83a05_62c000c1_c37358d5_63616d16_491c844c\",\"4\":-2058827829,\"5\":\"3164446\",\"7\":\"b64magic:NK,f,76\",\"9\":\"ANGjdJ8mqimbXxk2JQsqD1dmjMeuyinFaMmrWf0uVxPkkwdFZMmefFDSi2KNiKkz-rjWt0VpUt3tluGL_2WLTrLTSoW_D1ULhXcIhzf03F64TyWZk5kaGTz8Yb13Ysk\"},\"10\":\"GkEvYmxvYnN0b3JlL3Byb2QvZ21haWwtdXBsb2FkLzM3N2Y4MjUxLTJjYjMtNGE1Yi04NjdmLTU0MDU3MGIxYWU3Yiifko0BMiw5NmU4M2EwNV82MmMwMDBjMV9jMzczNThkNV82MzYxNmQxNl80OTFjODQ0YzjLj6OqCEieksEBWANiEGI2NG1hZ2ljOk5LLGYsNzZoAJoBQDc2OWUyNTNmMzZlMzFjZTZlZjgyODFjZTdjZTE4YjBmYTYzZTc0NDQ1MDlmNzhhMDdhZmRkMjcxYmRkMzllZGSqAQIIAQ==\",\"11\":1}],\"18\":\"1562634059674\",\"42\":0,\"43\":{\"1\":0,\"2\":0,\"3\":14,\"4\":0},\"52\":\"s:7b25e2896356085b|#msg-a:r1280593055912233690|0\"}";
+
module.exports = {
visible_emails_post_data: visible_emails_post_data,
parse_response_json_data: parse_response_json_data,
@@ -41,5 +45,7 @@ module.exports = {
new_gmail_read_action_body_params: new_gmail_read_action_body_params,
new_gmail_delete_action_body_params: new_gmail_delete_action_body_params,
new_gmail_open_email_action_body_params: new_gmail_open_email_action_body_params,
- new_gmail_new_email_body_params: new_gmail_new_email_body_params
+ new_gmail_new_email_body_params: new_gmail_new_email_body_params,
+ new_gmail_apply_label_action_body_params: new_gmail_apply_label_action_body_params,
+ new_gmail_sent_email_json: new_gmail_sent_email_json
};