diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b07b4b3a..93524e65 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,12 +35,19 @@ npm run dev # run dev build - bump version: manifest.json, package.json ## Run tests + +### elm tests ``` npx elm-test npx chokidar "{src,tests}/**/*.elm" -c "npx elm-test" npx elm-test ./tests/SpecificFile.elm ``` +### typescript tests +``` +npx chokidar "{typescript,typescript-tests}/**/*.ts" -c "npx jest" +``` + ## Code coverage ``` npm i -g elm-coverage diff --git a/README.md b/README.md index 78a50b25..a06ccc05 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,29 @@ An [Obsidian](https://obsidian.md/) plugin to make working with tasks a pleasure - Uses regular tasks/subtasks wherever they are in your vault. - Shows them on kanban style boards. -- Two column types supported: +- Two column types supported (any combination can be on a single board): - Date based (with daily/periodic notes support). - - Tag based (uses `#tags` to define columns). + - Tag based (use `#tags` to define columns). ## New -- Boards can have a mixture of date and tag based columns. -- Columns can be re-ordered (by dragging them on the settings pane). -- More flexible date based columns based on relative dates. -- Ability to use css snippets to - [set card hightlight color](#customising-card-highlight-color) based on tags. -- Board reordering; drag and drop tab headers or board names in the settings dialog. +- Choose files or directories to ignore when loading + tasks from notes. Handy if you use templates which contain + tasks that you don't want to see on your boards, or if you + want to speed up loading by skipping any files or folders + you know will not contain tasks you with to use with CardBoard. +- Confirmation step added when deleting cards. +- Can now choose to use either local or UTC time when marking tasks as complete. +- Shows the year of a task on the card if it is not due in + the current year. +- Bugfix: filter definitions dropdown is now scrollable. +- Bugfix: card content respects the _Text Font_ setting in + Obsidian _Appearance_ settings. +- Bugfix: use Obsidian _Font size_ for the CardBoard font size. +- Bugfix: fix issue where cards which move columns when + the date changes (at midnight) loose their content. +- Bugfix: (hopefully) fixed issues with where cards could appear + in unexpected columns when there is an `Other Tags` column. + ![date based board screenshot](/images/dateBoard.png?raw=true) @@ -36,22 +48,22 @@ When installed, you can launch the plugin: ![app ribbon icon](/images/ribbonIcon.png?raw=true) If you have no boards defined, you should get a dialog asking you to add a new -board. You can choose between 3 board types: +board. You can choose from one of 3 board types to get going: - **Date based**: looks like the main screenshot above. -- **Tag based**: uses tags to define the columns (you need to include tags on - your tasks or in front matter for this to work). +- **Tag based**: includes the built-in tag based columns. You will need to add + the tag columns you wish to include. - **Empty board**: has no pre-defined columns. -These are just to get you started. You can add/edit/re-order/delete columns -for these (or any board) via the plugin's settings. +These are just to get you started. You can mix date and tag based columns on +the same board: use the plugin's settings to add/edit/re-order/delete columns. ## Cards Any task in your vault can appear as a card in a column on a board. In order to do this, it must: - Be in a markdown file. -- Not be indented. +- Not be indented - it must be at the start of the line. - Use one of the commonmark supported unordered list formats: - `- [ ] Task title` - `* [ ] Task title` @@ -62,8 +74,8 @@ What appears on the card depends on what your task looks like: - Anything that is indented under a task will appear in the body of the task. - Indented tasks will appear as subtasks (all subtasks are grouped together). - Indented text will appear as notes. -- `#tags` in front matter or on the line of the task will - appear at the top of the card. +- `#tags` on the line of the task or included in the `tags` property of the note + containing the task will appear at the top of the card - Due date (if given) will appear at the bottom of the card. So, if you had the following in one of your markdown files: @@ -85,7 +97,7 @@ It will look something like this on a card on your board: ![example card](/images/card.png?raw=true) ### Marking a task as complete -If you mark an task as complete on the board it will be marked as completed in the markdown +If you mark a task as complete on the board it will be marked as completed in the markdown file (and vice-versa). If you mark as complete on the board, a completion timestamp is appended to the task: @@ -96,6 +108,9 @@ is appended to the task: See the [compatibility section](#other-plugin-compatibility) for details on how you can choose to use a format compatible with other plugins (or to choose not to add any completion text). +You can choose wether to use local or UTC time in completion timestamps via the plugin's +settings (in the `Global Settings` section). + If you have subtasks and the parent task is tagged as an _autocomplete_ task then the main task will be marked as complete when you tick off the final subtask: @@ -115,7 +130,7 @@ the task from your vault, it simply surrounds it with markdown `` tags: ``` ### Editing tasks (and hover preview) -Click on the edit icon to open the file containing the task. Cmd (or Ctrl on windows) +Click on the edit icon to open the note containing the task. Cmd (or Ctrl on windows) hover over the icon for the normal Obsidian hover preview. @@ -270,26 +285,28 @@ you can define a board that shows tasks tagged with these in separate columns: You do not need to inclue the `#` character at the start of the tag when defining which tag shold be used for a column. +#### Subtags +If you specify a tag with a trailing `/` in the settings for the column, +then the column will contain all tasks which have subtags of the tag, as well +as those with the _base_ tag. #### Sub-tasks Tasks with sub-tasks that have matching tags will also appear on the board. -#### Subtags -If you specify a tag with a trailing `/` in the settings for the column, -then the column will contain all subtags of the tag. - -#### Front Matter Tags +#### Tag Properties If you want to give all the tasks on a page the same tag, you can put it in the -page front matter: +properties of a note: ``` --- -tags: [ project1 ] +tags: + - recipe + - cooking --- # Project 1 -- [ ] this task will automatically have a project1 tag +- [ ] this task will automatically have the recipe and cooking tags ``` #### Hiding Tags @@ -309,7 +326,7 @@ You cannot have more that one of each of these on a board. ### Completed column You can include a complted column on your board. This will only include completed tasks that would have appeared in one of the other columns had it not been -completed; so it only contains tasks that _belong_ on the board. +completed; i.e. it only contains tasks that _belong_ on the board. Where you have columns based on tags and a task is shown in a column due to tags on sub-tasks it will only show in that column if those subtasks are incomplete. @@ -328,8 +345,8 @@ You cannot have more than one Completed column on a board. ### Board Filters You can filter which tasks appear on each board in the board settings. There are 3 -types of filter you can use: file, path, and #tags (which includes front matter tags). You can -use any combination of these on a per-board basis. +types of filter you can use: file, path, and #tags (which includes tags in note properties). +You can use any combination of these on a per-board basis. You can also: @@ -346,12 +363,14 @@ Filters are applied before tasks are placed onto a board: Plugin settings are accessible from the plugin view itself, via the settings icon above the board to the left of the tabs. You can: +- Choose files and paths you do not want to load any tasks from. - Create new boards (using the + icon next to the _Boards_ heading). - Configure your boards. - Customize the default names of the built-in columns. - Add/remove/edit/reorder columns. - Delete boards. - Choose whether to use Cardboard, Dataview or Tasks format for marking task completion. +- Choose whether to use local or UTC time when marking tasks as completed. - Choose to not use the date of daily notes files as the due date for tasks. The settings for your boards are saved in the @@ -369,7 +388,7 @@ then do ensure that your .obsidian directory is backed up. Cardboard is compatible with the *Due* and *Completion* date formats used in both [Tasks](https://obsidian-tasks-group.github.io/obsidian-tasks/) and [Dataview](https://blacksmithgu.github.io/obsidian-dataview/). -Dates from both of these are understood with no configuration. +Due dates from both of these are understood with no configuration. When marking a task as complete, you can choose which format to use via CardBoard's Global Settings: @@ -431,8 +450,11 @@ and/or set the width of the columns by changing the width setting. ## Limitations - Might not work that great on large vaults (as it parses all markdown files at startup). -- Might not work that great on large files (as it parses all markdown files, and doesn't use - any form of cache). + If you use folders in your vault and there are folders which you know will never contain + any tasks you wish to use with CardBoard you can configure CardBoard to ignore these. +- Might not work that great on large markdown files (as it parses all markdown files, and doesn't use + any form of cache). If you know any large markdown files will never contain tasks you + wish to use with Cardboard, you can add them to the ignore list in settings. - Might not be great on mobile (see previous, plus I haven't put any particular effort into making the interface mobile friendly - yet). diff --git a/TODO.md b/TODO.md index a3555a0f..5d66ed04 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,3 @@ -- bug ? if I make a column for "people/" it includes the card tagged with "people/fred" - as expected! However, if I also have an other tags column, this card appears here too - - not expected - - touch events - iPad ?? - show errors on settings pane ?? @@ -11,9 +7,6 @@ - if something is on a board because of a subtask tag and that line also has a due date on it, should I use that as the due date of the card? - dataview - what if there is a due date in the frontmatter? -- on tagboard if there is a todo with the tag defined in filter allow list - but no other tags then it appears in the others column. It feels like - it should really be in the untagged column. - check coverage and add tests - why is the case of the filename for MultiSelect.elm not being recognised properly? - add ts declarations to replace @ts-ignores: @@ -29,6 +22,14 @@ - and tripple up if you do it again - ... +# Mobile +- you can toggle mobile emulation by entering the following in Developer Tools > Console. + this.app.emulateMobile(!this.app.isMobile); +- use https://github.com/shabegom/obsidian-mobile-logging to console.log to a note + inside the vault. Think this does the same as: + https://gist.github.com/liamcain/3f21f1ee820cb30f18050d2f3ad85f3f + + # UI Improvements - nested subtasks are un-nested on cards - if I was going to sort this, would I want to support nested autocomplete? diff --git a/configExamples/data.0.12.0.json b/configExamples/data.0.12.0.json new file mode 100644 index 00000000..9308551c --- /dev/null +++ b/configExamples/data.0.12.0.json @@ -0,0 +1,361 @@ +{ + "version": "0.12.0", + "data": { + "boardConfigs": [ + { + "columns": [ + { + "tag": "undated", + "data": { + "collapsed": false, + "name": "Undated" + } + }, + { + "tag": "dated", + "data": { + "collapsed": false, + "name": "Today", + "range": { + "tag": "before", + "data": 1 + } + } + }, + { + "tag": "dated", + "data": { + "collapsed": false, + "name": "Tomorrow", + "range": { + "tag": "between", + "data": { + "from": 1, + "to": 1 + } + } + } + }, + { + "tag": "dated", + "data": { + "collapsed": false, + "name": "Future", + "range": { + "tag": "after", + "data": 1 + } + } + }, + { + "tag": "completed", + "data": { + "collapsed": true, + "index": 4, + "limit": 5, + "name": "Completed" + } + } + ], + "filters": [ + { + "tag": "tagFilter", + "data": "people/" + }, + { + "tag": "tagFilter", + "data": "home/" + } + ], + "filterPolarity": "Deny", + "filterScope": "TopLevelOnly", + "name": "Dated", + "showColumnTags": false, + "showFilteredTags": false + }, + { + "columns": [ + { + "tag": "untagged", + "data": { + "collapsed": true, + "name": "Untagged" + } + }, + { + "tag": "otherTags", + "data": { + "collapsed": true, + "name": "Other Tags" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Home/", + "tag": "home/" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Home", + "tag": "home" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Wellbeing", + "tag": "wellbeing" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": true, + "name": "Town", + "tag": "town" + } + }, + { + "tag": "completed", + "data": { + "collapsed": false, + "index": 6, + "limit": 10, + "name": "Completed" + } + } + ], + "filters": [], + "filterPolarity": "Allow", + "filterScope": "SubTasksOnly", + "name": "Tagged", + "showColumnTags": false, + "showFilteredTags": false + }, + { + "columns": [ + { + "tag": "otherTags", + "data": { + "collapsed": true, + "name": "Other Tags" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Backlog", + "tag": "status/backlog" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": true, + "name": "Triaged", + "tag": "status/triaged" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": true, + "name": "Blocked", + "tag": "status/blocked" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Doing", + "tag": "status/doing" + } + }, + { + "tag": "completed", + "data": { + "collapsed": false, + "index": 5, + "limit": 10, + "name": "Completed" + } + } + ], + "filters": [ + { + "tag": "tagFilter", + "data": "projects/project1" + } + ], + "filterPolarity": "Allow", + "filterScope": "Both", + "name": "Project 1", + "showColumnTags": false, + "showFilteredTags": false + }, + { + "columns": [ + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Kitchen", + "tag": "home/kitchen" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Outside", + "tag": "home/outside" + } + }, + { + "tag": "completed", + "data": { + "collapsed": false, + "index": 2, + "limit": 10, + "name": "Completed" + } + } + ], + "filters": [ + { + "tag": "tagFilter", + "data": "home" + }, + { + "tag": "tagFilter", + "data": "home/" + } + ], + "filterPolarity": "Allow", + "filterScope": "Both", + "name": "Home", + "showColumnTags": true, + "showFilteredTags": true + }, + { + "columns": [ + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "خانه", + "tag": "خانه" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "خانه/", + "tag": "خانه/" + } + }, + { + "tag": "completed", + "data": { + "collapsed": false, + "index": 2, + "limit": 10, + "name": "Completed" + } + } + ], + "filters": [], + "filterPolarity": "Allow", + "filterScope": "Both", + "name": "خانه", + "showColumnTags": true, + "showFilteredTags": true + }, + { + "columns": [ + { + "tag": "otherTags", + "data": { + "collapsed": true, + "name": "Other Tags" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": true, + "name": "Fred", + "tag": "people/fred" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": false, + "name": "Wilma", + "tag": "people/wilma" + } + }, + { + "tag": "namedTag", + "data": { + "collapsed": true, + "name": "Barney", + "tag": "people/barney" + } + }, + { + "tag": "completed", + "data": { + "collapsed": false, + "index": 4, + "limit": 10, + "name": "Completed" + } + } + ], + "filters": [ + { + "tag": "tagFilter", + "data": "people/" + } + ], + "filterPolarity": "Allow", + "filterScope": "Both", + "name": "People", + "showColumnTags": true, + "showFilteredTags": true + } + ], + "globalSettings": { + "defaultColumnNames": { + "today": "", + "tomorrow": "", + "future": "", + "undated": "", + "otherTags": "", + "untagged": "", + "completed": "" + }, + "filters": [ + { + "tag": "pathFilter", + "data": "example_tasks/templates" + } + ], + "ignoreFileNameDates": false, + "taskCompletionFormat": "ObsidianCardBoard", + "taskCompletionInLocalTime": true, + "taskCompletionShowUtcOffset": false + } + } +} \ No newline at end of file diff --git a/elm.json b/elm.json index 795f5555..0c5ef200 100644 --- a/elm.json +++ b/elm.json @@ -22,6 +22,7 @@ "elm-community/maybe-extra": "5.3.0", "elm-community/string-extra": "4.0.1", "justinmimbs/date": "4.0.1", + "justinmimbs/time-extra": "1.1.1", "mpizenberg/elm-pointer-events": "5.0.0", "pzp1997/assoc-list": "1.0.0", "robinheghan/fnv1a": "1.0.0", @@ -31,22 +32,22 @@ "indirect": { "elm/bytes": "1.0.8", "elm/file": "1.0.5", - "elm/project-metadata-utils": "1.0.2", - "elm/random": "1.0.0", "elm/url": "1.0.0", "elm/virtual-dom": "1.0.3", - "elm-community/dict-extra": "2.4.0", - "elm-explorations/test": "2.1.2", - "miniBill/elm-unicode": "1.0.3", - "rtfeldman/elm-hex": "1.0.0", - "stil4m/elm-syntax": "7.3.2", - "stil4m/structured-writer": "1.0.3" + "elm-community/dict-extra": "2.4.0" } }, "test-dependencies": { "direct": { "elm-explorations/test": "2.1.2" }, - "indirect": {} + "indirect": { + "elm/project-metadata-utils": "1.0.2", + "elm/random": "1.0.0", + "miniBill/elm-unicode": "1.0.3", + "rtfeldman/elm-hex": "1.0.0", + "stil4m/elm-syntax": "7.3.2", + "stil4m/structured-writer": "1.0.3" + } } } diff --git a/images/taskCompletionFormatSetting.png b/images/taskCompletionFormatSetting.png index 178cfc08..6c7da0a4 100644 Binary files a/images/taskCompletionFormatSetting.png and b/images/taskCompletionFormatSetting.png differ diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..68ded7ed --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,10 @@ +module.exports = { + preset: 'ts-jest', + transform: { + '^.+\\.ts?$': 'ts-jest', + }, + testRegex: '/typescript-tests/.*\\.(test|spec)?\\.(ts|tsx)$', + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], +}; + +export { }; diff --git a/package-lock.json b/package-lock.json index a4c264d1..80d0d399 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cardboard", - "version": "0.7.4", + "version": "0.7.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cardboard", - "version": "0.7.2", + "version": "0.7.5", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -23,8 +23,10 @@ "elm-test": "^0.19.1-revision12", "elm-ts-interop": "^0.0.8", "elm-webpack-loader": "^8.0.0", + "jest": "^29.7.0", "obsidian": "^1.4.11", "obsidian-daily-notes-interface": "^0.9.4", + "ts-jest": "^29.1.1", "ts-loader": "^9.5.0", "ts-node": "^10.9.1", "tslib": "^2.6.2", @@ -33,6 +35,19 @@ "webpack-cli": "^5.1.4" } }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@avh4/elm-format-darwin-arm64": { "version": "0.8.7-2", "resolved": "https://registry.npmjs.org/@avh4/elm-format-darwin-arm64/-/elm-format-darwin-arm64-0.8.7-2.tgz", @@ -99,41 +114,19 @@ ] }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { + "node_modules/@babel/code-frame/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", @@ -145,7 +138,7 @@ "node": ">=4" } }, - "node_modules/@babel/highlight/node_modules/chalk": { + "node_modules/@babel/code-frame/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", @@ -159,7 +152,7 @@ "node": ">=4" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { + "node_modules/@babel/code-frame/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", @@ -168,13 +161,13 @@ "color-name": "1.1.3" } }, - "node_modules/@babel/highlight/node_modules/color-name": { + "node_modules/@babel/code-frame/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", @@ -183,7 +176,7 @@ "node": ">=0.8.0" } }, - "node_modules/@babel/highlight/node_modules/has-flag": { + "node_modules/@babel/code-frame/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", @@ -192,7 +185,7 @@ "node": ">=4" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { + "node_modules/@babel/code-frame/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", @@ -204,2322 +197,4363 @@ "node": ">=4" } }, - "node_modules/@codemirror/state": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", - "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==", - "dev": true, - "peer": true - }, - "node_modules/@codemirror/view": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.7.1.tgz", - "integrity": "sha512-kYtS+uqYw/q/0ytYxpkqE1JVuK5NsbmBklWYhwLFTKO9gVuTdh/kDEeZPKorbqHcJ+P+ucrhcsS1czVweOpT2g==", + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, - "peer": true, - "dependencies": { - "@codemirror/state": "^6.1.4", - "style-mod": "^4.0.0", - "w3c-keyname": "^2.2.4" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@babel/core": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", + "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": ">=12" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@babel/core/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, - "engines": { - "node": ">=10.0.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@elm_binaries/darwin_arm64": { - "version": "0.19.1-0", - "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_arm64/-/darwin_arm64-0.19.1-0.tgz", - "integrity": "sha512-mjbsH7BNHEAmoE2SCJFcfk5fIHwFIpxtSgnEAqMsVLpBUFoEtAeX+LQ+N0vSFJB3WAh73+QYx/xSluxxLcL6dA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@elm_binaries/darwin_x64": { - "version": "0.19.1-0", - "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_x64/-/darwin_x64-0.19.1-0.tgz", - "integrity": "sha512-QGUtrZTPBzaxgi9al6nr+9313wrnUVHuijzUK39UsPS+pa+n6CmWyV/69sHZeX9qy6UfeugE0PzF3qcUiy2GDQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@elm_binaries/linux_x64": { - "version": "0.19.1-0", - "resolved": "https://registry.npmjs.org/@elm_binaries/linux_x64/-/linux_x64-0.19.1-0.tgz", - "integrity": "sha512-T1ZrWVhg2kKAsi8caOd3vp/1A3e21VuCpSG63x8rDie50fHbCytTway9B8WHEdnBFv4mYWiA68dzGxYCiFmU2w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@elm_binaries/win32_x64": { - "version": "0.19.1-0", - "resolved": "https://registry.npmjs.org/@elm_binaries/win32_x64/-/win32_x64-0.19.1-0.tgz", - "integrity": "sha512-yDleiXqSE9EcqKtd9SkC/4RIW8I71YsXzMPL79ub2bBPHjWTcoyyeBbYjoOB9SxSlArJ74HaoBApzT6hY7Zobg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@babel/helper-compilation-targets/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, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "dependencies": { + "yallist": "^3.0.2" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/@babel/helper-compilation-targets/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, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=6.9.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", - "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "jest-get-type": "^29.2.0" + "@babel/types": "^7.22.15" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@jest/schemas": "^29.0.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/types": "^7.22.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@babel/helpers": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz", + "integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, - "optional": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, "engines": { - "node": ">=14" + "node": ">=6.9.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "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, - "engines": { - "node": ">=10" + "dependencies": { + "color-convert": "^1.9.0" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">=4" } }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "defer-to-connect": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/codemirror": { - "version": "5.60.8", - "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", - "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", + "node_modules/@babel/parser": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, - "dependencies": { - "@types/tern": "*" + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "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, "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "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, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "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, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "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, "dependencies": { - "@types/istanbul-lib-report": "*" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/jest": { - "version": "29.5.8", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", - "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", + "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, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/node": { - "version": "20.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", - "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "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, "dependencies": { - "undici-types": "~5.26.4" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "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, "dependencies": { - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "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, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/tern": { - "version": "0.23.7", - "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.7.tgz", - "integrity": "sha512-0YS9XCZ0LAhlP11HV9SqncUYyz9Ggsgc7Om/AmchKvoeFyj0qPaJmX6rJ93mJVExizWDzUMb49gAtVpI1uHd8Q==", + "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, "dependencies": { - "@types/estree": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/webpack": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz", - "integrity": "sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==", + "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, "dependencies": { - "@types/node": "*", - "tapable": "^2.2.0", - "webpack": "^5" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/yargs": { - "version": "17.0.18", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.18.tgz", - "integrity": "sha512-eIJR1UER6ur3EpKM3d+2Pgd+ET+k6Kn9B4ZItX0oPjjVI5PrfaRjKyLT5UYendDpLuoiJMNJvovLQbEXqhsPaw==", + "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, "dependencies": { - "@types/yargs-parser": "*" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "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, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/@babel/traverse": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", "dev": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/@babel/types": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "dependencies": { - "@xtuc/long": "4.2.2" + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "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 }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "node_modules/@codemirror/state": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", + "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } + "peer": true }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "node_modules/@codemirror/view": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.7.1.tgz", + "integrity": "sha512-kYtS+uqYw/q/0ytYxpkqE1JVuK5NsbmBklWYhwLFTKO9gVuTdh/kDEeZPKorbqHcJ+P+ucrhcsS1czVweOpT2g==", "dev": true, + "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "node_modules/@elm_binaries/darwin_arm64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_arm64/-/darwin_arm64-0.19.1-0.tgz", + "integrity": "sha512-mjbsH7BNHEAmoE2SCJFcfk5fIHwFIpxtSgnEAqMsVLpBUFoEtAeX+LQ+N0vSFJB3WAh73+QYx/xSluxxLcL6dA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "node_modules/@elm_binaries/darwin_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/darwin_x64/-/darwin_x64-0.19.1-0.tgz", + "integrity": "sha512-QGUtrZTPBzaxgi9al6nr+9313wrnUVHuijzUK39UsPS+pa+n6CmWyV/69sHZeX9qy6UfeugE0PzF3qcUiy2GDQ==", + "cpu": [ + "x64" + ], "dev": true, - "engines": { - "node": ">=14.15.0" + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@elm_binaries/linux_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/linux_x64/-/linux_x64-0.19.1-0.tgz", + "integrity": "sha512-T1ZrWVhg2kKAsi8caOd3vp/1A3e21VuCpSG63x8rDie50fHbCytTway9B8WHEdnBFv4mYWiA68dzGxYCiFmU2w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@elm_binaries/win32_x64": { + "version": "0.19.1-0", + "resolved": "https://registry.npmjs.org/@elm_binaries/win32_x64/-/win32_x64-0.19.1-0.tgz", + "integrity": "sha512-yDleiXqSE9EcqKtd9SkC/4RIW8I71YsXzMPL79ub2bBPHjWTcoyyeBbYjoOB9SxSlArJ74HaoBApzT6hY7Zobg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "engines": { + "node": ">=12" } }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=14.15.0" + "node": ">=12" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">=14.15.0" + "node": ">=12" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=0.4.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "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==", + "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, "dependencies": { - "type-fest": "^0.21.3" + "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" - }, - "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==", + "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, "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==", + "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, "dependencies": { - "color-convert": "^2.0.1" + "@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": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@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": ">= 8" + "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/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "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, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">= 4.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.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 + "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, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "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, + "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": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "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, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "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, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@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/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@jest/reporters/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, "dependencies": { - "fill-range": "^7.0.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "node_modules/@jest/reporters/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, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "has-flag": "^4.0.0" }, - "bin": { - "browserslist": "cli.js" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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, + "dependencies": { + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "@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/buffer-from": { + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "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, + "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, + "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/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "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, + "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.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "optional": true, "engines": { - "node": ">=10.6.0" + "node": ">=14" } }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "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 + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "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, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "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, - "engines": { - "node": ">=6" + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001441", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", - "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", + "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, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", + "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, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/codemirror": { + "version": "5.60.8", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", + "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", + "dev": true, + "dependencies": { + "@types/tern": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.4.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", + "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "dev": true + }, + "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, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.8.tgz", + "integrity": "sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz", + "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/tern": { + "version": "0.23.7", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.7.tgz", + "integrity": "sha512-0YS9XCZ0LAhlP11HV9SqncUYyz9Ggsgc7Om/AmchKvoeFyj0qPaJmX6rJ93mJVExizWDzUMb49gAtVpI1uHd8Q==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/webpack": { + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz", + "integrity": "sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.18", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.18.tgz", + "integrity": "sha512-eIJR1UER6ur3EpKM3d+2Pgd+ET+k6Kn9B4ZItX0oPjjVI5PrfaRjKyLT5UYendDpLuoiJMNJvovLQbEXqhsPaw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/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, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "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, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "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, + "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, + "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, + "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-istanbul/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, + "bin": { + "semver": "bin/semver.js" + } + }, + "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, + "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, + "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, + "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 + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "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" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "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, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "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 + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001572", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz", + "integrity": "sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==", + "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" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/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, + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", + "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "yargs": "^13.3.0" + }, + "bin": { + "chokidar": "index.js" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", + "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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 + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, + "node_modules/commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/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 + }, + "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, + "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/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true } - ] + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "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, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.617", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.617.tgz", + "integrity": "sha512-sYNE3QxcDS4ANW1k4S/wWYMXjCVcFSOX3Bg8jpuMFaXt/x8JCmp0R1Xe1ZXDX4WXnSRBf+GJ/3eGWicUuQq5cg==", + "dev": true + }, + "node_modules/elm": { + "version": "0.19.1-6", + "resolved": "https://registry.npmjs.org/elm/-/elm-0.19.1-6.tgz", + "integrity": "sha512-mKYyierHICPdMx/vhiIacdPmTPnh889gjHOZ75ZAoCxo3lZmSWbGP8HMw78wyctJH0HwvTmeKhlYSWboQNYPeQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "elm": "bin/elm" + }, + "engines": { + "node": ">=7.0.0" + }, + "optionalDependencies": { + "@elm_binaries/darwin_arm64": "0.19.1-0", + "@elm_binaries/darwin_x64": "0.19.1-0", + "@elm_binaries/linux_x64": "0.19.1-0", + "@elm_binaries/win32_x64": "0.19.1-0" + } + }, + "node_modules/elm-format": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/elm-format/-/elm-format-0.8.7.tgz", + "integrity": "sha512-sVzFXfWnb+6rzXK+q3e3Ccgr6/uS5mFbFk1VSmigC+x2XZ28QycAa7lS8owl009ALPhRQk+pZ95Eq5ANjpEZsQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "elm-format": "bin/elm-format" + }, + "optionalDependencies": { + "@avh4/elm-format-darwin-arm64": "0.8.7-2", + "@avh4/elm-format-darwin-x64": "0.8.7-2", + "@avh4/elm-format-linux-arm64": "0.8.7-2", + "@avh4/elm-format-linux-x64": "0.8.7-2", + "@avh4/elm-format-win32-x64": "0.8.7-2" + } + }, + "node_modules/elm-hot": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/elm-hot/-/elm-hot-1.1.6.tgz", + "integrity": "sha512-zYZJlfs7Gt4BdjA+D+857K+XAWzwwySJmXCgFpHW1dIEfaHSZCIPYPf7/jinZBLfKRkOAlKzI32AA84DY50g7Q==", + "dev": true + }, + "node_modules/elm-reloader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/elm-reloader/-/elm-reloader-1.0.0.tgz", + "integrity": "sha512-G1mmjiXuc2CDDm/NzFq68XkPljrHl2t9bR3dBCJ5YLzAuW8baSS5Amr0NlIIMoV1i1kPQ/CexOwxLLEcgQCVOQ==", + "dev": true, + "dependencies": { + "elm-hot": "^1.1.6" + }, + "peerDependencies": { + "elm-webpack-loader": "^8.0.0" + } + }, + "node_modules/elm-review": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/elm-review/-/elm-review-2.10.3.tgz", + "integrity": "sha512-9gBqLc5Xm3v9Ncpf8y2haEaBZZyMX25vmwQkrNqSIaNYQ2vdGOIx1eyqRtt1xwX5O8pZdqU8IWC/ENyTrOTKbw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "chokidar": "^3.5.2", + "cross-spawn": "^7.0.3", + "elm-tooling": "^1.14.1", + "fastest-levenshtein": "^1.0.16", + "find-up": "^4.1.0", + "folder-hash": "^3.3.0", + "fs-extra": "^9.0.0", + "glob": "^7.1.4", + "got": "^11.8.5", + "graceful-fs": "^4.2.11", + "minimist": "^1.2.6", + "ora": "^5.4.0", + "path-key": "^3.1.1", + "prompts": "^2.2.1", + "rimraf": "^5.0.0", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.1.1", + "which": "^2.0.2", + "wrap-ansi": "^6.2.0" + }, + "bin": { + "elm-review": "bin/elm-review" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/jfmengels" + } + }, + "node_modules/elm-review/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/elm-review/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/elm-review/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/elm-review/node_modules/rimraf/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/elm-solve-deps-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz", + "integrity": "sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw==", + "dev": true + }, + "node_modules/elm-test": { + "version": "0.19.1-revision12", + "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.1-revision12.tgz", + "integrity": "sha512-5GV3WkJ8R/faOP1hwElQdNuCt8tKx2+1lsMrdeIYWSFz01Kp9gJl/R6zGtp4QUyrUtO8KnHsxjHrQNUf2CHkrg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "commander": "^9.4.1", + "cross-spawn": "^7.0.3", + "elm-solve-deps-wasm": "^1.0.2", + "glob": "^8.0.3", + "graceful-fs": "^4.2.10", + "split": "^1.0.1", + "which": "^2.0.2", + "xmlbuilder": "^15.1.1" + }, + "bin": { + "elm-test": "bin/elm-test" + }, + "engines": { + "node": ">=12.20.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==", + "node_modules/elm-test/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "balanced-match": "^1.0.0" + } + }, + "node_modules/elm-test/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/elm-test/node_modules/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=10" } }, - "node_modules/chokidar-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", - "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "node_modules/elm-tooling": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/elm-tooling/-/elm-tooling-1.15.0.tgz", + "integrity": "sha512-quRE5LGJyrkPBoJ3MvFQ5RGgf80J0L0d3NkduStvXh4TmZuMXNC3Z/l2ZRoq2UTUaNWeYfO1Zx5wns1AvsTrnw==", + "dev": true, + "bin": { + "elm-tooling": "index.js" + } + }, + "node_modules/elm-ts-interop": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/elm-ts-interop/-/elm-ts-interop-0.0.8.tgz", + "integrity": "sha512-Ull6tl4MZk3tQKn5fna1qiHCXa99AYgzIL+4FSJiTcfHsOy8Se3F7ww0QyrCIFGVtzP/2F99rbzRI3MHH6Rdag==", "dev": true, "dependencies": { "chokidar": "^3.5.2", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "yargs": "^13.3.0" + "commander": "^7.1.0", + "cross-spawn": "^7.0.3", + "node-elm-compiler": "^5.0.5", + "typescript": "^4.1.5" }, "bin": { - "chokidar": "index.js" - }, - "engines": { - "node": ">= 8.10.0" + "elm-ts-interop": "src/index.js" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/elm-ts-interop/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "engines": { - "node": ">=6.0" + "node": ">= 10" } }, - "node_modules/ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "node_modules/elm-ts-interop/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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=8" + "node": ">=4.2.0" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/elm-webpack-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/elm-webpack-loader/-/elm-webpack-loader-8.0.0.tgz", + "integrity": "sha512-R49j9GOGbZ+PjrktAzYzjUgf6w+RHOIUNWLfOVdc7OoGG52SreEk63l/bLJV31HwLE8PU6KANEnzeZ3238fAUg==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "loader-utils": "^2.0.0", + "node-elm-compiler": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=8.0.0" + }, + "peerDependencies": { + "elm": "^0.19.1-3 || 0.19.0-no-deps" } }, - "node_modules/cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", + "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, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "once": "^1.4.0" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, "engines": { - "node": ">=6" + "node": ">=10.13.0" } }, - "node_modules/cliui/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==", + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true, - "dependencies": { - "color-convert": "^1.9.0" + "bin": { + "envinfo": "dist/cli.js" }, "engines": { "node": ">=4" } }, - "node_modules/cliui/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==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "is-arrayish": "^0.2.1" } }, - "node_modules/cliui/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==", + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=6" + "node": ">=8.0.0" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/esrecurse/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, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "engines": { - "node": ">=0.8" + "node": ">=4.0" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "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": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "node_modules/execa/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, - "dependencies": { - "mimic-response": "^1.0.0" + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "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, "dependencies": { - "color-name": "~1.1.4" + "@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": ">=7.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.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==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "engines": { - "node": "^12.20.0 || >=14" + "node": ">= 4.9.1" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "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, + "dependencies": { + "bser": "2.1.1" + } }, - "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==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/find-elm-dependencies": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/find-elm-dependencies/-/find-elm-dependencies-2.0.4.tgz", + "integrity": "sha512-x/4w4fVmlD2X4PD9oQ+yh9EyaQef6OtEULdMGBTuWx0Nkppvo2Z/bAiQioW2n+GdRYKypME2b9OmYTw5tw5qDg==", "dev": true, "dependencies": { - "ms": "2.1.2" + "firstline": "^1.2.0", + "lodash": "^4.17.19" + }, + "bin": { + "find-elm-dependencies": "bin/cli.js" }, "engines": { - "node": ">=6.0" + "node": ">=4.0.0" + } + }, + "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, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/firstline": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/firstline/-/firstline-1.3.1.tgz", + "integrity": "sha512-ycwgqtoxujz1dm0kjkBFOPQMESxB9uKc/PlD951dQDIG+tBXRpYZC2UmJb0gDxopQ1ZX6oyRQN3goRczYu7Deg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.4.0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/folder-hash": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-3.3.3.tgz", + "integrity": "sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A==", "dev": true, "dependencies": { - "mimic-response": "^3.1.0" + "debug": "^4.1.1", + "graceful-fs": "~4.2.0", + "minimatch": "~3.0.4" }, - "engines": { - "node": ">=10" + "bin": { + "folder-hash": "bin/folder-hash" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "clone": "^1.0.2" + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { "node": ">=10" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, - "node_modules/diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/elm": { - "version": "0.19.1-6", - "resolved": "https://registry.npmjs.org/elm/-/elm-0.19.1-6.tgz", - "integrity": "sha512-mKYyierHICPdMx/vhiIacdPmTPnh889gjHOZ75ZAoCxo3lZmSWbGP8HMw78wyctJH0HwvTmeKhlYSWboQNYPeQ==", + "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, - "hasInstallScript": true, - "bin": { - "elm": "bin/elm" - }, "engines": { - "node": ">=7.0.0" - }, - "optionalDependencies": { - "@elm_binaries/darwin_arm64": "0.19.1-0", - "@elm_binaries/darwin_x64": "0.19.1-0", - "@elm_binaries/linux_x64": "0.19.1-0", - "@elm_binaries/win32_x64": "0.19.1-0" + "node": ">=6.9.0" } }, - "node_modules/elm-format": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/elm-format/-/elm-format-0.8.7.tgz", - "integrity": "sha512-sVzFXfWnb+6rzXK+q3e3Ccgr6/uS5mFbFk1VSmigC+x2XZ28QycAa7lS8owl009ALPhRQk+pZ95Eq5ANjpEZsQ==", + "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, - "hasInstallScript": true, - "bin": { - "elm-format": "bin/elm-format" - }, - "optionalDependencies": { - "@avh4/elm-format-darwin-arm64": "0.8.7-2", - "@avh4/elm-format-darwin-x64": "0.8.7-2", - "@avh4/elm-format-linux-arm64": "0.8.7-2", - "@avh4/elm-format-linux-x64": "0.8.7-2", - "@avh4/elm-format-win32-x64": "0.8.7-2" + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/elm-hot": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/elm-hot/-/elm-hot-1.1.6.tgz", - "integrity": "sha512-zYZJlfs7Gt4BdjA+D+857K+XAWzwwySJmXCgFpHW1dIEfaHSZCIPYPf7/jinZBLfKRkOAlKzI32AA84DY50g7Q==", - "dev": true + "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, + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/elm-reloader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/elm-reloader/-/elm-reloader-1.0.0.tgz", - "integrity": "sha512-G1mmjiXuc2CDDm/NzFq68XkPljrHl2t9bR3dBCJ5YLzAuW8baSS5Amr0NlIIMoV1i1kPQ/CexOwxLLEcgQCVOQ==", + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { - "elm-hot": "^1.1.6" + "pump": "^3.0.0" }, - "peerDependencies": { - "elm-webpack-loader": "^8.0.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/elm-review": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/elm-review/-/elm-review-2.10.3.tgz", - "integrity": "sha512-9gBqLc5Xm3v9Ncpf8y2haEaBZZyMX25vmwQkrNqSIaNYQ2vdGOIx1eyqRtt1xwX5O8pZdqU8IWC/ENyTrOTKbw==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { - "chalk": "^4.0.0", - "chokidar": "^3.5.2", - "cross-spawn": "^7.0.3", - "elm-tooling": "^1.14.1", - "fastest-levenshtein": "^1.0.16", - "find-up": "^4.1.0", - "folder-hash": "^3.3.0", - "fs-extra": "^9.0.0", - "glob": "^7.1.4", - "got": "^11.8.5", - "graceful-fs": "^4.2.11", - "minimist": "^1.2.6", - "ora": "^5.4.0", - "path-key": "^3.1.1", - "prompts": "^2.2.1", - "rimraf": "^5.0.0", - "strip-ansi": "^6.0.0", - "terminal-link": "^2.1.1", - "which": "^2.0.2", - "wrap-ansi": "^6.2.0" - }, - "bin": { - "elm-review": "bin/elm-review" + "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": ">=10.0.0" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/jfmengels" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/elm-review/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/elm-review/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, - "node_modules/elm-review/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "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, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/elm-review/node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10.19.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/elm-solve-deps-wasm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/elm-solve-deps-wasm/-/elm-solve-deps-wasm-1.0.2.tgz", - "integrity": "sha512-qnwo7RO9IO7jd9SLHvIy0rSOEIlc/tNMTE9Cras0kl+b161PVidW4FvXo0MtXU8GAKi/2s/HYvhcnpR/NNQ1zw==", + "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 }, - "node_modules/elm-test": { - "version": "0.19.1-revision12", - "resolved": "https://registry.npmjs.org/elm-test/-/elm-test-0.19.1-revision12.tgz", - "integrity": "sha512-5GV3WkJ8R/faOP1hwElQdNuCt8tKx2+1lsMrdeIYWSFz01Kp9gJl/R6zGtp4QUyrUtO8KnHsxjHrQNUf2CHkrg==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "commander": "^9.4.1", - "cross-spawn": "^7.0.3", - "elm-solve-deps-wasm": "^1.0.2", - "glob": "^8.0.3", - "graceful-fs": "^4.2.10", - "split": "^1.0.1", - "which": "^2.0.2", - "xmlbuilder": "^15.1.1" - }, - "bin": { - "elm-test": "bin/elm-test" + "function-bind": "^1.1.1" }, "engines": { - "node": ">=12.20.0" + "node": ">= 0.4.0" } }, - "node_modules/elm-test/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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 + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" } }, - "node_modules/elm-test/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "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, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10.17.0" } }, - "node_modules/elm-test/node_modules/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/elm-tooling": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/elm-tooling/-/elm-tooling-1.15.0.tgz", - "integrity": "sha512-quRE5LGJyrkPBoJ3MvFQ5RGgf80J0L0d3NkduStvXh4TmZuMXNC3Z/l2ZRoq2UTUaNWeYfO1Zx5wns1AvsTrnw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "bin": { - "elm-tooling": "index.js" + "engines": { + "node": ">=0.8.19" } }, - "node_modules/elm-ts-interop": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/elm-ts-interop/-/elm-ts-interop-0.0.8.tgz", - "integrity": "sha512-Ull6tl4MZk3tQKn5fna1qiHCXa99AYgzIL+4FSJiTcfHsOy8Se3F7ww0QyrCIFGVtzP/2F99rbzRI3MHH6Rdag==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { - "chokidar": "^3.5.2", - "commander": "^7.1.0", - "cross-spawn": "^7.0.3", - "node-elm-compiler": "^5.0.5", - "typescript": "^4.1.5" - }, - "bin": { - "elm-ts-interop": "src/index.js" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/elm-ts-interop/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=10.13.0" } }, - "node_modules/elm-ts-interop/node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "dependencies": { + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=4.2.0" + "node": ">=8" } }, - "node_modules/elm-webpack-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/elm-webpack-loader/-/elm-webpack-loader-8.0.0.tgz", - "integrity": "sha512-R49j9GOGbZ+PjrktAzYzjUgf6w+RHOIUNWLfOVdc7OoGG52SreEk63l/bLJV31HwLE8PU6KANEnzeZ3238fAUg==", + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { - "loader-utils": "^2.0.0", - "node-elm-compiler": "^5.0.0" - }, - "engines": { - "node": ">=8.0.0" + "has": "^1.0.3" }, - "peerDependencies": { - "elm": "^0.19.1-3 || 0.19.0-no-deps" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/emojis-list": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "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, - "dependencies": { - "once": "^1.4.0" + "engines": { + "node": ">=6" } }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=0.10.0" } }, - "node_modules/envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "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==", + "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, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, "engines": { - "node": ">=8.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, "engines": { - "node": ">=4.0" + "node": ">=0.10.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "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, "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, "engines": { - "node": ">=4.0" + "node": ">=10" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "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, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.8.x" + "node": ">=10" } }, - "node_modules/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", + "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, "dependencies": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, "engines": { - "node": ">= 4.9.1" + "node": ">=8" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/find-elm-dependencies": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/find-elm-dependencies/-/find-elm-dependencies-2.0.4.tgz", - "integrity": "sha512-x/4w4fVmlD2X4PD9oQ+yh9EyaQef6OtEULdMGBTuWx0Nkppvo2Z/bAiQioW2n+GdRYKypME2b9OmYTw5tw5qDg==", + "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, "dependencies": { - "firstline": "^1.2.0", - "lodash": "^4.17.19" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" }, "bin": { - "find-elm-dependencies": "bin/cli.js" + "jest": "bin/jest.js" }, "engines": { - "node": ">=4.0.0" + "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/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "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, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/firstline": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/firstline/-/firstline-1.3.1.tgz", - "integrity": "sha512-ycwgqtoxujz1dm0kjkBFOPQMESxB9uKc/PlD951dQDIG+tBXRpYZC2UmJb0gDxopQ1ZX6oyRQN3goRczYu7Deg==", + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=6.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/folder-hash": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-3.3.3.tgz", - "integrity": "sha512-SDgHBgV+RCjrYs8aUwCb9rTgbTVuSdzvFmLaChsLre1yf+D64khCW++VYciaByZ8Rm0uKF8R/XEpXuTRSGUM1A==", + "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, "dependencies": { - "debug": "^4.1.1", - "graceful-fs": "~4.2.0", - "minimatch": "~3.0.4" - }, - "bin": { - "folder-hash": "bin/folder-hash" + "@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": ">=6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "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, + "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" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/jest-cli/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, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/jest-cli/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, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "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==", + "node_modules/jest-cli/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, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=10" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/jest-cli/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, "dependencies": { - "pump": "^3.0.0" + "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/jest-cli/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, + "engines": { + "node": ">=12" + } + }, + "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, "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" + "@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": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + }, + "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, "dependencies": { - "is-glob": "^4.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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, "dependencies": { - "brace-expansion": "^1.1.7" + "detect-newline": "^3.0.0" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "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, "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "@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": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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 - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "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, "dependencies": { - "function-bind": "^1.1.1" + "@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": ">= 0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "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, "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" + "@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": ">=10.19.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/jest-haste-map/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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "@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/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/jest-haste-map/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, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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==", + "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, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "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, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "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, "dependencies": { - "binary-extensions": "^2.0.0" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "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, "dependencies": { - "has": "^1.0.3" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "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, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "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==", + "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, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "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, "dependencies": { - "is-extglob": "^2.1.1" + "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": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "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, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "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, + "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": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/jest-runner/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, "dependencies": { - "isobject": "^3.0.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { "node": ">=10" }, @@ -2527,110 +4561,155 @@ "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 - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/jest-runner/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, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + }, + "node_modules/jest-runner/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, "dependencies": { - "@isaacs/cliui": "^8.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", + "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, "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", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "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-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", + "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, + "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-matcher-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", - "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", + "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, "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "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-message-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", - "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", + "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, "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", - "@types/stack-utils": "^2.0.0", + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "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-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", + "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, + "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, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "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" @@ -2671,6 +4750,31 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "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, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "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", @@ -2740,6 +4844,21 @@ "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -2787,6 +4906,12 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -2830,12 +4955,36 @@ "node": ">=10" } }, + "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, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "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", @@ -2938,6 +5087,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3032,10 +5187,16 @@ "which": "bin/which" } }, + "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 + }, "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -3059,6 +5220,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/obsidian": { "version": "1.4.11", "resolved": "git+ssh://git@github.com/obsidianmd/obsidian-api.git#791214a68d0dc322b88e5abce617bdf603cc2a2d", @@ -3184,6 +5357,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3263,6 +5454,15 @@ "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, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -3276,12 +5476,12 @@ } }, "node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", + "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, "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -3333,6 +5533,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -3457,6 +5673,15 @@ "node": ">=8" } }, + "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, + "engines": { + "node": ">=10" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -3647,6 +5872,12 @@ "node": "*" } }, + "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 + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -3668,6 +5899,19 @@ "safe-buffer": "~5.2.0" } }, + "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, + "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", @@ -3722,6 +5966,36 @@ "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, + "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, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/style-mod": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", @@ -3884,12 +6158,41 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "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, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "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 + }, + "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, + "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", @@ -3902,6 +6205,58 @@ "node": ">=8.0" } }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/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, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-loader": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", @@ -3980,6 +6335,15 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "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, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -4021,9 +6385,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -4033,6 +6397,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -4040,7 +6408,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -4067,6 +6435,30 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "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/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/w3c-keyname": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", @@ -4074,6 +6466,15 @@ "dev": true, "peer": true }, + "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, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -4284,6 +6685,19 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "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, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -4437,6 +6851,18 @@ "engines": { "node": ">=6" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 727e267a..57603819 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build": "webpack --progress --color --mode=production", "dev": "webpack --mode=development --watch --progress --color", "generate": "elm-ts-interop --definition-module InteropDefinitions --output src/Main/index.d.ts", - "test": "elm-test tests" + "test": "elm-test tests", + "test-ts": "jest" }, "keywords": [], "author": "roovo", @@ -24,8 +25,10 @@ "elm-test": "^0.19.1-revision12", "elm-ts-interop": "^0.0.8", "elm-webpack-loader": "^8.0.0", + "jest": "^29.7.0", "obsidian": "^1.4.11", "obsidian-daily-notes-interface": "^0.9.4", + "ts-jest": "^29.1.1", "ts-loader": "^9.5.0", "ts-node": "^10.9.1", "tslib": "^2.6.2", diff --git a/scripts/generate_example_tasks.rb b/scripts/generate_example_tasks.rb index e6feb8ad..411c414c 100755 --- a/scripts/generate_example_tasks.rb +++ b/scripts/generate_example_tasks.rb @@ -38,6 +38,7 @@ - [ ] something with #foobar an RTL non-sub tag @due(#{Date.today.strftime("%Y-%m-%d")}) #خانه foo bar baz #خانه/آشپزخانه #one two and another line #foobar something else +- [ ] something I should have done a year ago @due(#{(Date.today - 370).strftime("%Y-%m-%d")}) """ end @@ -64,14 +65,6 @@ """ end -daily_note_template = File.join(target_directory, "daily_note_template.md") - -File.open(daily_note_template, "w") do |file| - file.write """ -# Daily note template -""" -end - future_tasks = File.join(target_directory, "future_tasks.md") File.open(future_tasks, "w") do |file| @@ -80,6 +73,8 @@ - [ ] next week thing @due(#{(Date.today + 7).strftime("%Y-%m-%d")}) - [ ] day after tomorrow thing @due(#{(Date.today + 2).strftime("%Y-%m-%d")}) +- [ ] two years out thing @due(#{(Date.today + 740).strftime("%Y-%m-%d")}) +- [ ] one year out thing @due(#{(Date.today + 370).strftime("%Y-%m-%d")}) """ end @@ -129,6 +124,7 @@ } ``` """ +end colab_tasks = File.join(target_directory, "colab.md") @@ -145,4 +141,19 @@ """ end + +template_directory = File.join(target_directory, "templates") +template_tasks = File.join(template_directory, "template.md") + +Dir.mkdir(template_directory) + +File.open(template_tasks, "w") do |file| + file.write """ +# A template + +- [ ] templated task with no date or tags +- [ ] templated task for today @due(#{(Date.today).strftime("%Y-%m-%d")}) +- [ ] templated task for #people/barney barney + +""" end diff --git a/src/Board.elm b/src/Board.elm index 674ac342..5fc5790d 100644 --- a/src/Board.elm +++ b/src/Board.elm @@ -78,7 +78,11 @@ applyFilters taskList polarity scope filters = taskList else - TaskList.filter (\t -> filterMode (operator << Filter.isAllowed scope t) filters) taskList + TaskList.filter + (\t -> + filterMode (operator << TaskItem.isAllowed scope t) filters + ) + taskList configureDueDates : Bool -> TaskList -> TaskList diff --git a/src/BoardConfig.elm b/src/BoardConfig.elm index bf06db09..de796365 100644 --- a/src/BoardConfig.elm +++ b/src/BoardConfig.elm @@ -6,6 +6,7 @@ module BoardConfig exposing , columns , decoder_v_0_10_0 , decoder_v_0_11_0 + , decoder_v_0_12_0 , decoder_v_0_1_0 , decoder_v_0_2_0 , decoder_v_0_3_0 @@ -127,19 +128,9 @@ encoder = ] -decoder_v_0_11_0 : TsDecode.Decoder BoardConfig -decoder_v_0_11_0 = - (TsDecode.succeed Config - |> TsDecode.required "columns" Columns.decoder - |> TsDecode.required "filters" (TsDecode.list Filter.decoder) - |> TsDecode.required "filterPolarity" Filter.polarityDecoder - |> TsDecode.required "filterScope" Filter.scopeDecoder - |> TsDecode.required "name" TsDecode.string - |> TsDecode.required "showColumnTags" TsDecode.bool - |> TsDecode.required "showFilteredTags" TsDecode.bool - ) - |> TsDecode.map configureOtherTagsColumn - |> TsDecode.map BoardConfig +decoder_v_0_12_0 : TsDecode.Decoder BoardConfig +decoder_v_0_12_0 = + decoder_v_0_11_0 @@ -186,6 +177,21 @@ type alias LocalColumnConfig = } +decoder_v_0_11_0 : TsDecode.Decoder BoardConfig +decoder_v_0_11_0 = + (TsDecode.succeed Config + |> TsDecode.required "columns" Columns.decoder + |> TsDecode.required "filters" (TsDecode.list Filter.decoder) + |> TsDecode.required "filterPolarity" Filter.polarityDecoder + |> TsDecode.required "filterScope" Filter.scopeDecoder + |> TsDecode.required "name" TsDecode.string + |> TsDecode.required "showColumnTags" TsDecode.bool + |> TsDecode.required "showFilteredTags" TsDecode.bool + ) + |> TsDecode.map configureOtherTagsColumn + |> TsDecode.map BoardConfig + + decoder_v_0_10_0 : TsDecode.Decoder BoardConfig decoder_v_0_10_0 = TsDecode.oneOf diff --git a/src/Card.elm b/src/Card.elm index a6d265e2..ae05840b 100644 --- a/src/Card.elm +++ b/src/Card.elm @@ -14,6 +14,7 @@ module Card exposing , tagsId , taskItem , taskItemId + , title ) import Date exposing (Date) @@ -49,6 +50,32 @@ fromTaskItem idPrefix tagsToHide taskItem_ = -- INFO +allTags : Card -> TagList +allTags (Card _ tagList _) = + tagList + + +descendantTasks : Card -> List ( String, TaskItem ) +descendantTasks (Card idPrefix _ item) = + TaskItem.descendantTasks item + |> List.map (\sub -> ( idPrefix ++ ":" ++ TaskItem.id sub, sub )) + + +displayTags : Card -> TagList +displayTags = + TaskItem.tags << taskItem + + +editButtonId : Card -> String +editButtonId card = + id card ++ ":editButton" + + +filePath : Card -> String +filePath (Card _ _ item) = + TaskItem.filePath item + + highlight : Date -> Card -> Highlight highlight datestamp (Card _ _ item) = case ( TaskItem.isCompleted item, TaskItem.due item ) of @@ -74,16 +101,6 @@ id ((Card idPrefix _ _) as card) = idPrefix ++ ":" ++ taskItemId card -editButtonId : Card -> String -editButtonId card = - id card ++ ":editButton" - - -filePath : Card -> String -filePath (Card _ _ item) = - TaskItem.filePath item - - markdownWithIds : Card -> List { id : String, markdown : String } markdownWithIds card = let @@ -139,7 +156,7 @@ markdownWithIds card = topLevelTagsMarkdown : String topLevelTagsMarkdown = TaskItem.topLevelTags item - |> TagList.toList + |> TagList.toStrings |> List.map (String.append "#") |> String.join " " in @@ -164,27 +181,11 @@ notesId card = id card ++ ":notes" -allTags : Card -> TagList -allTags (Card _ tagList _) = - tagList - - -displayTags : Card -> TagList -displayTags = - TaskItem.tags << taskItem - - tagsId : Card -> String tagsId card = id card ++ ":tags" -descendantTasks : Card -> List ( String, TaskItem ) -descendantTasks (Card idPrefix _ item) = - TaskItem.descendantTasks item - |> List.map (\sub -> ( idPrefix ++ ":" ++ TaskItem.id sub, sub )) - - taskItem : Card -> TaskItem taskItem (Card _ _ item) = item @@ -193,3 +194,8 @@ taskItem (Card _ _ item) = taskItemId : Card -> String taskItemId (Card _ _ item) = TaskItem.id item + + +title : Card -> String +title (Card _ _ item) = + TaskItem.title item diff --git a/src/Column/OtherTags.elm b/src/Column/OtherTags.elm index 2b8f18e1..f0f19db3 100644 --- a/src/Column/OtherTags.elm +++ b/src/Column/OtherTags.elm @@ -105,15 +105,40 @@ tagsToHide (OtherTagsColumn _ _ tth _) = addTaskItem : TaskItem -> OtherTagsColumn -> ( OtherTagsColumn, PlacementResult ) addTaskItem taskItem ((OtherTagsColumn c ots tth tl) as otherTagsColumn) = - if belongs ots taskItem then - if isCompleted ots taskItem then - ( otherTagsColumn, PlacementResult.CompletedInThisColumn ) + let + candidates : List TaskItem + candidates = + TaskItem.asSingleTaskItems taskItem + |> List.filter TaskItem.hasTags + |> List.map removeOtherColumnTags + |> List.filter TaskItem.hasTags + + removeOtherColumnTags : TaskItem -> TaskItem + removeOtherColumnTags item = + let + helper : String -> TaskItem -> TaskItem + helper tag taskItem_ = + if TaskItem.hasThisTag tag taskItem_ then + TaskItem.removeMatchingTags tag taskItem_ + + else + taskItem_ + in + List.foldl helper item ots + in + if List.length candidates == 0 then + ( otherTagsColumn, PlacementResult.DoesNotBelong ) - else - ( OtherTagsColumn c ots tth (TaskList.add taskItem tl), PlacementResult.Placed ) + else if + TaskItem.isCompleted taskItem + || List.all TaskItem.isCompleted candidates + then + ( otherTagsColumn, PlacementResult.CompletedInThisColumn ) else - ( otherTagsColumn, PlacementResult.DoesNotBelong ) + ( OtherTagsColumn c ots tth (TaskList.add taskItem tl) + , PlacementResult.Placed + ) setCollapse : Bool -> OtherTagsColumn -> OtherTagsColumn @@ -150,11 +175,6 @@ updateName newName (OtherTagsColumn c ots tth tl) = -- PRIVATE -belongs : List String -> TaskItem -> Bool -belongs tags item = - TaskItem.hasTaskWithTagOtherThanThese tags item - - config : OtherTagsColumn -> Config config (OtherTagsColumn c _ _ _) = c @@ -166,11 +186,3 @@ configEncoder = [ TsEncode.required "collapsed" .collapsed TsEncode.bool , TsEncode.required "name" .name TsEncode.string ] - - -isCompleted : List String -> TaskItem -> Bool -isCompleted columnTags taskItem = - TaskItem.isCompleted taskItem - || (TaskItem.hasSubtasks taskItem - && not (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese columnTags taskItem) - ) diff --git a/src/DefaultColumnNames.elm b/src/DefaultColumnNames.elm index c59f3e7e..2f8420e3 100644 --- a/src/DefaultColumnNames.elm +++ b/src/DefaultColumnNames.elm @@ -5,6 +5,7 @@ module DefaultColumnNames exposing , nameFor , v_0_10_0_decoder , v_0_11_0_decoder + , v_0_12_0_decoder , v_0_7_0_decoder , v_0_8_0_decoder , v_0_9_0_decoder @@ -77,6 +78,28 @@ nameFor column defaultColumnNames = -- SERIALIZE +v_0_12_0_decoder : TsDecode.Decoder DefaultColumnNames +v_0_12_0_decoder = + v_0_11_0_decoder + + +encoder : TsEncode.Encoder DefaultColumnNames +encoder = + TsEncode.object + [ TsEncode.required "today" (fromMaybe .today) TsEncode.string + , TsEncode.required "tomorrow" (fromMaybe .tomorrow) TsEncode.string + , TsEncode.required "future" (fromMaybe .future) TsEncode.string + , TsEncode.required "undated" (fromMaybe .undated) TsEncode.string + , TsEncode.required "otherTags" (fromMaybe .otherTags) TsEncode.string + , TsEncode.required "untagged" (fromMaybe .untagged) TsEncode.string + , TsEncode.required "completed" (fromMaybe .completed) TsEncode.string + ] + + + +-- LEGACY + + v_0_11_0_decoder : TsDecode.Decoder DefaultColumnNames v_0_11_0_decoder = TsDecode.succeed DefaultColumnNames @@ -116,19 +139,6 @@ v_0_7_0_decoder = |> TsDecode.andMap (TsDecode.field "completed" <| TsDecode.map toMaybe TsDecode.string) -encoder : TsEncode.Encoder DefaultColumnNames -encoder = - TsEncode.object - [ TsEncode.required "today" (fromMaybe .today) TsEncode.string - , TsEncode.required "tomorrow" (fromMaybe .tomorrow) TsEncode.string - , TsEncode.required "future" (fromMaybe .future) TsEncode.string - , TsEncode.required "undated" (fromMaybe .undated) TsEncode.string - , TsEncode.required "otherTags" (fromMaybe .otherTags) TsEncode.string - , TsEncode.required "untagged" (fromMaybe .untagged) TsEncode.string - , TsEncode.required "completed" (fromMaybe .completed) TsEncode.string - ] - - -- PRIVATE diff --git a/src/Filter.elm b/src/Filter.elm index 51eb05af..19138436 100644 --- a/src/Filter.elm +++ b/src/Filter.elm @@ -1,5 +1,5 @@ module Filter exposing - ( Filter + ( Filter(..) , Polarity(..) , Scope(..) , decoder @@ -9,7 +9,6 @@ module Filter exposing , encoder , filterType , filterTypes - , isAllowed , ofType , polarityDecoder , polarityEncoder @@ -22,8 +21,6 @@ module Filter exposing import DecodeHelpers import Json.Encode as JE -import List.Extra as LE -import TaskItem exposing (TaskItem) import TsJson.Decode as TsDecode import TsJson.Encode as TsEncode @@ -208,27 +205,6 @@ value filter = f -isAllowed : Scope -> TaskItem -> Filter -> Bool -isAllowed scope taskItem filter = - case filter of - FileFilter filePath -> - TaskItem.isFromFile filePath taskItem - - PathFilter path -> - fileIsFromPath (TaskItem.filePath taskItem) path - - TagFilter tag -> - case scope of - TopLevelOnly -> - TaskItem.topLevelTaskHasThisTag tag taskItem - - SubTasksOnly -> - TaskItem.descendantTaskHasThisTag tag taskItem - - Both -> - TaskItem.hasThisTag tag taskItem - - -- MODIFICATION @@ -252,41 +228,3 @@ updatePath oldPath newPath filter = TagFilter _ -> filter - - - --- HELPERS - - -fileIsFromPath : String -> String -> Bool -fileIsFromPath file path = - let - pathComponents : List String - pathComponents = - path - |> String.replace "\\" "/" - |> String.split "/" - |> List.filter (not << String.isEmpty) - - filePathComponents : List String - filePathComponents = - file - |> String.replace "\\" "/" - |> String.split "/" - |> List.reverse - |> List.drop 1 - |> List.reverse - |> List.filter (not << String.isEmpty) - - isComponentMatching : Int -> String -> Bool - isComponentMatching index pathComponent = - case LE.getAt index filePathComponents of - Nothing -> - False - - Just filePathComponent -> - filePathComponent == pathComponent - in - pathComponents - |> List.indexedMap isComponentMatching - |> List.all identity diff --git a/src/Form/BoardConfig.elm b/src/Form/BoardConfig.elm index 22ee79b8..6c26356e 100644 --- a/src/Form/BoardConfig.elm +++ b/src/Form/BoardConfig.elm @@ -3,7 +3,6 @@ module Form.BoardConfig exposing , fromNewBoardForm , init , mapColumnsForm - -- , optionsForSelect , safeDecoder , toggleShowColumnTags , toggleShowFilteredTags @@ -124,7 +123,6 @@ safeDecoder = --- INFO -- MODIFICATION diff --git a/src/Form/SafeDecoder.elm b/src/Form/SafeDecoder.elm index 5989838b..a5161006 100644 --- a/src/Form/SafeDecoder.elm +++ b/src/Form/SafeDecoder.elm @@ -10,7 +10,7 @@ module Form.SafeDecoder exposing , lift , listOf , map - , map10 + , map13 , map2 , map7 , minBound @@ -147,8 +147,8 @@ map7 f d1 d2 d3 d4 d5 d6 d7 = |> field d7 -map10 : - (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> value) +map13 : + (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> m -> value) -> Decoder input a -> Decoder input b -> Decoder input c @@ -159,8 +159,11 @@ map10 : -> Decoder input h -> Decoder input i -> Decoder input j + -> Decoder input k + -> Decoder input l + -> Decoder input m -> Decoder input value -map10 f d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 = +map13 f d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 = top f |> field d1 |> field d2 @@ -172,6 +175,9 @@ map10 f d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 = |> field d8 |> field d9 |> field d10 + |> field d11 + |> field d12 + |> field d13 diff --git a/src/Form/Settings.elm b/src/Form/Settings.elm index 0fbd1988..9b0bd56e 100644 --- a/src/Form/Settings.elm +++ b/src/Form/Settings.elm @@ -15,6 +15,8 @@ module Form.Settings exposing , safeDecoder , switchToBoard , toggleIgnoreFileNameDate + , toggleTaskCompletionInLocalTime + , toggleTaskCompletionShowUtcOffset , updateDefaultColumnName , updateTaskCompletionFormat ) @@ -22,6 +24,7 @@ module Form.Settings exposing import BoardConfig exposing (BoardConfig) import DefaultColumnNames exposing (DefaultColumnNames) import DragAndDrop.BeaconPosition as BeaconPosition exposing (BeaconPosition) +import Filter exposing (Filter) import Form.BoardConfig as BoardConfigForm exposing (BoardConfigForm) import Form.Column exposing (ColumnForm) import Form.Columns as ColumnsForm exposing (ColumnsForm) @@ -41,10 +44,13 @@ import Settings exposing (Settings) type alias SettingsForm = { boardConfigForms : SafeZipper BoardConfigForm , completed : String + , filters : List Filter , future : String , ignoreFileNameDates : Bool , otherTags : String , taskCompletionFormat : String + , taskCompletionInLocalTime : Bool + , taskCompletionShowUtcOffset : Bool , today : String , tomorrow : String , undated : String @@ -88,10 +94,13 @@ init settings = in { boardConfigForms = boardConfigForms_ , completed = Maybe.withDefault "" defaultColumnNames_.completed + , filters = globalSettings_.filters , future = Maybe.withDefault "" defaultColumnNames_.future , ignoreFileNameDates = globalSettings_.ignoreFileNameDates , otherTags = Maybe.withDefault "" defaultColumnNames_.otherTags , taskCompletionFormat = taskCompletionFormat_ + , taskCompletionInLocalTime = globalSettings_.taskCompletionInLocalTime + , taskCompletionShowUtcOffset = globalSettings_.taskCompletionShowUtcOffset , today = Maybe.withDefault "" defaultColumnNames_.today , tomorrow = Maybe.withDefault "" defaultColumnNames_.tomorrow , undated = Maybe.withDefault "" defaultColumnNames_.undated @@ -105,13 +114,16 @@ init settings = safeDecoder : SD.Decoder SettingsForm Settings safeDecoder = - SD.map10 settingsBuilder + SD.map13 settingsBuilder boardConfigFormsDecoder completedDecoder + filtersDecoder futureDecoder ignoreFileNameDatesDecoder otherTagsDecoder taskCompletionFormatDecoder + taskCompletionInLocalTimeDecoder + taskCompletionShowUtcOffsetDecoder todayDecoder tomorrowDecoder undatedDecoder @@ -227,6 +239,16 @@ toggleIgnoreFileNameDate settingsForm = { settingsForm | ignoreFileNameDates = not settingsForm.ignoreFileNameDates } +toggleTaskCompletionInLocalTime : SettingsForm -> SettingsForm +toggleTaskCompletionInLocalTime settingsForm = + { settingsForm | taskCompletionInLocalTime = not settingsForm.taskCompletionInLocalTime } + + +toggleTaskCompletionShowUtcOffset : SettingsForm -> SettingsForm +toggleTaskCompletionShowUtcOffset settingsForm = + { settingsForm | taskCompletionShowUtcOffset = not settingsForm.taskCompletionShowUtcOffset } + + updateDefaultColumnName : String -> String -> SettingsForm -> SettingsForm updateDefaultColumnName column newName settingsForm = case column of @@ -295,6 +317,12 @@ completedDecoder = |> SD.lift .completed +filtersDecoder : SD.Decoder SettingsForm (List Filter) +filtersDecoder = + SD.identity + |> SD.lift .filters + + futureDecoder : SD.Decoder SettingsForm (Maybe String) futureDecoder = SD.identity @@ -320,16 +348,19 @@ otherTagsDecoder = settingsBuilder : SafeZipper BoardConfig -> Maybe String + -> List Filter -> Maybe String -> Bool -> Maybe String -> GlobalSettings.TaskCompletionFormat + -> Bool + -> Bool -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Settings -settingsBuilder bc com fut ifn ots tcf tod tom und unt = +settingsBuilder bc com fts fut ifn ots tcf clt cso tod tom und unt = let defaultColumnNames_ : DefaultColumnNames defaultColumnNames_ = @@ -344,9 +375,12 @@ settingsBuilder bc com fut ifn ots tcf tod tom und unt = globalSettings : GlobalSettings globalSettings = - { taskCompletionFormat = tcf - , defaultColumnNames = defaultColumnNames_ + { defaultColumnNames = defaultColumnNames_ + , filters = fts , ignoreFileNameDates = ifn + , taskCompletionFormat = tcf + , taskCompletionInLocalTime = clt + , taskCompletionShowUtcOffset = cso } in { boardConfigs = bc @@ -375,6 +409,18 @@ taskCompletionFormatDecoder = |> SD.lift .taskCompletionFormat +taskCompletionInLocalTimeDecoder : SD.Decoder SettingsForm Bool +taskCompletionInLocalTimeDecoder = + SD.identity + |> SD.lift .taskCompletionInLocalTime + + +taskCompletionShowUtcOffsetDecoder : SD.Decoder SettingsForm Bool +taskCompletionShowUtcOffsetDecoder = + SD.identity + |> SD.lift .taskCompletionShowUtcOffset + + todayDecoder : SD.Decoder SettingsForm (Maybe String) todayDecoder = SD.identity diff --git a/src/GlobalSettings.elm b/src/GlobalSettings.elm index 4c79e31e..aef78a94 100644 --- a/src/GlobalSettings.elm +++ b/src/GlobalSettings.elm @@ -1,10 +1,13 @@ module GlobalSettings exposing ( GlobalSettings , TaskCompletionFormat(..) + , TaskCompletionSettings , default , encoder + , taskCompletionSettings , v_0_10_0_decoder , v_0_11_0_decoder + , v_0_12_0_decoder , v_0_5_0_decoder , v_0_6_0_decoder , v_0_7_0_decoder @@ -13,6 +16,7 @@ module GlobalSettings exposing ) import DefaultColumnNames exposing (DefaultColumnNames) +import Filter exposing (Filter) import Json.Encode as JE import TsJson.Decode as TsDecode import TsJson.Encode as TsEncode @@ -30,17 +34,30 @@ type TaskCompletionFormat type alias GlobalSettings = - { taskCompletionFormat : TaskCompletionFormat - , defaultColumnNames : DefaultColumnNames + { defaultColumnNames : DefaultColumnNames + , filters : List Filter , ignoreFileNameDates : Bool + , taskCompletionFormat : TaskCompletionFormat + , taskCompletionInLocalTime : Bool + , taskCompletionShowUtcOffset : Bool + } + + +type alias TaskCompletionSettings = + { format : TaskCompletionFormat + , inLocalTime : Bool + , showUtcOffset : Bool } default : GlobalSettings default = - { taskCompletionFormat = ObsidianCardBoard - , defaultColumnNames = DefaultColumnNames.default + { defaultColumnNames = DefaultColumnNames.default + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = ObsidianCardBoard + , taskCompletionInLocalTime = True + , taskCompletionShowUtcOffset = True } @@ -51,65 +68,116 @@ default = encoder : TsEncode.Encoder GlobalSettings encoder = TsEncode.object - [ TsEncode.required "taskCompletionFormat" .taskCompletionFormat taskCompletionFormatEncoder - , TsEncode.required "defaultColumnNames" .defaultColumnNames DefaultColumnNames.encoder + [ TsEncode.required "defaultColumnNames" .defaultColumnNames DefaultColumnNames.encoder + , TsEncode.required "filters" .filters <| TsEncode.list Filter.encoder , TsEncode.required "ignoreFileNameDates" .ignoreFileNameDates TsEncode.bool + , TsEncode.required "taskCompletionFormat" .taskCompletionFormat taskCompletionFormatEncoder + , TsEncode.required "taskCompletionInLocalTime" .taskCompletionInLocalTime TsEncode.bool + , TsEncode.required "taskCompletionShowUtcOffset" .taskCompletionShowUtcOffset TsEncode.bool ] +v_0_12_0_decoder : TsDecode.Decoder GlobalSettings +v_0_12_0_decoder = + TsDecode.succeed GlobalSettings + |> TsDecode.andMap (TsDecode.field "defaultColumnNames" DefaultColumnNames.v_0_12_0_decoder) + |> TsDecode.andMap (TsDecode.field "filters" <| TsDecode.list Filter.decoder) + |> TsDecode.andMap (TsDecode.field "ignoreFileNameDates" TsDecode.bool) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.field "taskCompletionInLocalTime" TsDecode.bool) + |> TsDecode.andMap (TsDecode.field "taskCompletionShowUtcOffset" TsDecode.bool) + + + +-- INFO + + +taskCompletionSettings : GlobalSettings -> TaskCompletionSettings +taskCompletionSettings globalSettings = + { format = globalSettings.taskCompletionFormat + , inLocalTime = globalSettings.taskCompletionInLocalTime + , showUtcOffset = globalSettings.taskCompletionShowUtcOffset + } + + + +-- LEGACY + + v_0_11_0_decoder : TsDecode.Decoder GlobalSettings v_0_11_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.field "defaultColumnNames" DefaultColumnNames.v_0_11_0_decoder) + |> TsDecode.andMap (TsDecode.succeed []) |> TsDecode.andMap (TsDecode.field "ignoreFileNameDates" TsDecode.bool) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.succeed False) v_0_10_0_decoder : TsDecode.Decoder GlobalSettings v_0_10_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.field "columnNames" DefaultColumnNames.v_0_10_0_decoder) + |> TsDecode.andMap (TsDecode.succeed []) |> TsDecode.andMap (TsDecode.field "ignoreFileNameDates" TsDecode.bool) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.succeed False) v_0_9_0_decoder : TsDecode.Decoder GlobalSettings v_0_9_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.field "columnNames" DefaultColumnNames.v_0_9_0_decoder) + |> TsDecode.andMap (TsDecode.succeed []) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) |> TsDecode.andMap (TsDecode.succeed False) v_0_8_0_decoder : TsDecode.Decoder GlobalSettings v_0_8_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.field "columnNames" DefaultColumnNames.v_0_8_0_decoder) + |> TsDecode.andMap (TsDecode.succeed []) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) |> TsDecode.andMap (TsDecode.succeed False) v_0_7_0_decoder : TsDecode.Decoder GlobalSettings v_0_7_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.field "columnNames" DefaultColumnNames.v_0_7_0_decoder) + |> TsDecode.andMap (TsDecode.succeed []) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) |> TsDecode.andMap (TsDecode.succeed False) v_0_6_0_decoder : TsDecode.Decoder GlobalSettings v_0_6_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.succeed DefaultColumnNames.default) + |> TsDecode.andMap (TsDecode.succeed []) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.field "taskCompletionFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) |> TsDecode.andMap (TsDecode.succeed False) v_0_5_0_decoder : TsDecode.Decoder GlobalSettings v_0_5_0_decoder = TsDecode.succeed GlobalSettings - |> TsDecode.andMap (TsDecode.field "taskUpdateFormat" taskCompletionFormatDecoder) |> TsDecode.andMap (TsDecode.succeed DefaultColumnNames.default) + |> TsDecode.andMap (TsDecode.succeed []) + |> TsDecode.andMap (TsDecode.succeed False) + |> TsDecode.andMap (TsDecode.field "taskUpdateFormat" taskCompletionFormatDecoder) + |> TsDecode.andMap (TsDecode.succeed False) |> TsDecode.andMap (TsDecode.succeed False) diff --git a/src/InteropPorts.elm b/src/InteropPorts.elm index a7adb94b..e5392714 100644 --- a/src/InteropPorts.elm +++ b/src/InteropPorts.elm @@ -16,7 +16,7 @@ port module InteropPorts exposing import Card exposing (Card) import DataviewTaskCompletion exposing (DataviewTaskCompletion) import DragAndDrop.Coords exposing (Coords) -import GlobalSettings exposing (TaskCompletionFormat) +import GlobalSettings exposing (TaskCompletionSettings) import InteropDefinitions import Json.Decode import Json.Encode @@ -86,14 +86,14 @@ requestFilterCandidates = |> interopFromElm -rewriteTasks : DataviewTaskCompletion -> TaskCompletionFormat -> TimeWithZone -> String -> List TaskItem -> Cmd msg -rewriteTasks dataviewTaskCompletion taskCompletionFormat timeWithZone filePath taskItems = +rewriteTasks : DataviewTaskCompletion -> TaskCompletionSettings -> TimeWithZone -> String -> List TaskItem -> Cmd msg +rewriteTasks dataviewTaskCompletion taskCompletionSettings timeWithZone filePath taskItems = let rewriteDetails : TaskItem -> { lineNumber : Int, originalText : String, newText : String } rewriteDetails taskItem = { lineNumber = TaskItem.lineNumber taskItem , originalText = TaskItem.originalText taskItem - , newText = TaskItem.toToggledString dataviewTaskCompletion taskCompletionFormat timeWithZone taskItem + , newText = TaskItem.toToggledString dataviewTaskCompletion taskCompletionSettings timeWithZone taskItem } in { filePath = filePath, tasks = List.map rewriteDetails taskItems } diff --git a/src/Main.elm b/src/Main.elm index 0b16e042..ca999ad1 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -23,8 +23,8 @@ import Task import TaskItem import TaskList exposing (TaskList) import TextDirection exposing (TextDirection) -import Time -import TimeWithZone +import Time exposing (Posix) +import TimeWithZone exposing (TimeWithZone) main : Program JD.Value Model Msg @@ -54,7 +54,7 @@ init flags = session = Session.fromFlags okFlags in - ( Boards session + ( Boards (BoardPage.init session) |> forceAddWhenNoBoards , Cmd.batch [ InteropPorts.updateSettings <| Session.settings session @@ -67,9 +67,9 @@ init flags = forceAddWhenNoBoards : Model -> Model forceAddWhenNoBoards model = case model of - Boards session -> - if SafeZipper.length (Session.boardConfigs session) == 0 then - Settings (SettingsPage.init session) + Boards _ -> + if SafeZipper.length (Session.boardConfigs <| toSession model) == 0 then + Settings (SettingsPage.init <| toSession model) else model @@ -83,15 +83,15 @@ forceAddWhenNoBoards model = type Model - = Boards Session + = Boards BoardPage.Model | Settings SettingsPage.Model mapSession : (Session -> Session) -> Model -> Model mapSession fn model = case model of - Boards session -> - Boards <| fn session + Boards boardPageModel -> + Boards <| BoardPage.mapSession fn boardPageModel Settings settingsPageModel -> Settings <| SettingsPage.mapSession fn settingsPageModel @@ -100,8 +100,8 @@ mapSession fn model = toSession : Model -> Session toSession model = case model of - Boards session -> - session + Boards boardPageModel -> + BoardPage.toSession boardPageModel Settings settingsPageModel -> SettingsPage.toSession settingsPageModel @@ -127,9 +127,9 @@ type Msg | GotBoardPageMsg BoardPage.Msg | GotSettingsPageMsg SettingsPage.Msg | KeyDown KeyValue - | ReceiveTime ( Time.Zone, Time.Posix ) + | ReceiveTime ( Time.Zone, Posix ) | ShowBoard Int - | Tick Time.Posix + | Tick Posix | VaultFileAdded MarkdownFile | VaultFileDeleted String | VaultFileRenamed ( String, String ) @@ -237,8 +237,48 @@ update msg model = ) ( Tick time, _ ) -> - ( mapSession (Session.timeIs time) model - , Cmd.none + let + cmd : Cmd Msg + cmd = + if newDate == oldDate then + Cmd.none + + else + cmdForDateChange newSession + + newDate : Int + newDate = + newSession + |> Session.timeWithZone + |> TimeWithZone.toDate + |> Date.toRataDie + + newSession : Session + newSession = + Session.timeIs time <| toSession model + + offsetPosix : Int -> TimeWithZone -> TimeWithZone + offsetPosix secs timeWithZone = + let + foo : Posix -> Posix + foo posix = + posix + |> Time.posixToMillis + |> (\m -> m - (secs * 1000)) + |> Time.millisToPosix + in + { timeWithZone | time = foo time } + + oldDate : Int + oldDate = + toSession model + |> Session.timeWithZone + |> offsetPosix 1 + |> TimeWithZone.toDate + |> Date.toRataDie + in + ( mapSession (always newSession) model + , cmd ) ( VaultFileAdded markdownFile, _ ) -> @@ -306,6 +346,31 @@ cmdForFilterPathRename newPath session = Cmd.none +cmdForDateChange : Session -> Cmd Msg +cmdForDateChange session = + let + today : Date + today = + Session.timeWithZone session + |> TimeWithZone.toDate + + cards : List Card + cards = + Session.taskList session + |> TaskList.filter TaskItem.isDated + |> Boards.init (Session.uniqueId session) (Session.boardConfigs session) + |> Boards.cards (Session.ignoreFileNameDates session) today + in + if List.isEmpty cards then + Cmd.none + + else + Cmd.batch + [ InteropPorts.displayTaskMarkdown cards + , InteropPorts.addHoverToCardEditButtons cards + ] + + cmdForTaskRedraws : String -> Session -> Cmd Msg cmdForTaskRedraws newPath session = let @@ -347,6 +412,7 @@ updateWith toModel toMsg ( subModel, subCmd, sessionMsg ) = toModel subModel |> toSession |> Session.updateSettings newSettings + |> BoardPage.init |> Boards , Cmd.map toMsg subCmd ) @@ -428,11 +494,11 @@ toKeyValue string = view : Model -> Html Msg view model = case model of - Boards session -> + Boards boardPageModel -> viewPage GotBoardPageMsg GotSettingsPageMsg - { content = BoardPage.view session + { content = BoardPage.view boardPageModel , modal = Nothing } @@ -440,7 +506,9 @@ view model = viewPage GotBoardPageMsg GotSettingsPageMsg - { content = BoardPage.view (SettingsPage.toSession settingsPageModel) + { content = + BoardPage.view + (BoardPage.init <| SettingsPage.toSession settingsPageModel) , modal = Just <| SettingsPage.view settingsPageModel } diff --git a/src/MarkdownFile.elm b/src/MarkdownFile.elm index 8b8358ab..daed7328 100644 --- a/src/MarkdownFile.elm +++ b/src/MarkdownFile.elm @@ -1,4 +1,7 @@ -module MarkdownFile exposing (MarkdownFile, decoder) +module MarkdownFile exposing + ( MarkdownFile + , decoder + ) import TagList exposing (TagList) import TsJson.Decode as TsDecode @@ -59,7 +62,12 @@ contentDecoder contents = frontMatterDecoder : YD.Decoder (List String) frontMatterDecoder = - YD.field "tags" (YD.list YD.string) + YD.field "tags" + (YD.oneOf + [ YD.list YD.string + , invalidListDecoder + ] + ) frontMatterAndBodyFrom : String -> ( Maybe String, Int, Maybe String ) @@ -96,6 +104,20 @@ hasFrontMatter splitContents = startsWithWhiteSpace splitContents && List.length splitContents > 2 +invalidListDecoder : YD.Decoder (List String) +invalidListDecoder = + let + buildList : String -> YD.Decoder (List String) + buildList str = + str + |> String.split "," + |> List.map String.trim + |> YD.succeed + in + YD.string + |> YD.andThen buildList + + startsWithWhiteSpace : List String -> Bool startsWithWhiteSpace splitContents = List.head splitContents diff --git a/src/Page/Board.elm b/src/Page/Board.elm index 50f831e0..b0bcd38c 100644 --- a/src/Page/Board.elm +++ b/src/Page/Board.elm @@ -1,5 +1,9 @@ module Page.Board exposing - ( Msg(..) + ( Model + , Msg(..) + , init + , mapSession + , toSession , update , view ) @@ -33,16 +37,68 @@ import TimeWithZone exposing (TimeWithZone) +-- MODEL + + +type Model + = ViewingBoard Session + | DeletingCard String String Session + + +init : Session -> Model +init session = + ViewingBoard session + + +cancelCurrentState : Model -> Model +cancelCurrentState model = + ViewingBoard (toSession model) + + +deleteCardRequested : String -> String -> Model -> Model +deleteCardRequested title cardId model = + DeletingCard title cardId (toSession model) + + +deleteCardConfirmed : Model -> Model +deleteCardConfirmed model = + ViewingBoard (toSession model) + + +mapSession : (Session -> Session) -> Model -> Model +mapSession fn model = + case model of + ViewingBoard session -> + ViewingBoard <| fn session + + DeletingCard title cardId session -> + DeletingCard title cardId <| fn session + + +toSession : Model -> Session +toSession model = + case model of + ViewingBoard session -> + session + + DeletingCard _ _ session -> + session + + + -- UPDATE type Msg - = ElementDragged DragData + = DeleteConfirmed String + | ElementDragged DragData + | ModalCancelClicked + | ModalCloseClicked | SettingsClicked | TabHeaderMouseDown ( String, DragTracker.ClientData ) | TabSelected Int | TaskItemEditClicked String - | TaskItemDeleteClicked String + | TaskItemDeleteClicked String String | TaskItemToggled String | ToggleColumnCollapse Int Bool @@ -52,56 +108,74 @@ dragType = "card-board-tag-header" -update : Msg -> Session -> ( Session, Cmd Msg, Session.Msg ) -update msg session = +update : Msg -> Model -> ( Model, Cmd Msg, Session.Msg ) +update msg model = case msg of + DeleteConfirmed cardId -> + ( deleteCardConfirmed model + , cmdIfHasTask cardId model InteropPorts.deleteTask + , Session.NoOp + ) + ElementDragged dragData -> case dragData.dragAction of DragData.Move -> if dragData.dragType == dragType then - ( session - |> updateBoardOrder (Session.dragTracker session) dragData - |> Session.moveDragable dragData + ( model + |> updateBoardOrder (Session.dragTracker <| toSession model) dragData + |> (mapSession <| Session.moveDragable dragData) , Cmd.none , Session.NoOp ) else - ( session, Cmd.none, Session.NoOp ) + ( model, Cmd.none, Session.NoOp ) DragData.Stop -> - ( Session.stopTrackingDragable session - , InteropPorts.updateSettings <| Session.settings session + ( mapSession Session.stopTrackingDragable model + , InteropPorts.updateSettings <| Session.settings <| toSession model , Session.NoOp ) + ModalCancelClicked -> + ( cancelCurrentState model + , Cmd.none + , Session.NoOp + ) + + ModalCloseClicked -> + ( cancelCurrentState model + , Cmd.none + , Session.NoOp + ) + SettingsClicked -> - ( session + ( model , Cmd.none , Session.SettingsClicked ) TabHeaderMouseDown ( domId, clientData ) -> - ( Session.waitForDrag clientData session + ( mapSession (Session.waitForDrag clientData) model , InteropPorts.trackDraggable dragType clientData.clientPos domId , Session.NoOp ) TabSelected tabIndex -> - ( Session.switchToBoardAt tabIndex session + ( mapSession (Session.switchToBoardAt tabIndex) model , Cmd.none , Session.NoOp ) - TaskItemDeleteClicked id -> - ( session - , cmdIfHasTask id session InteropPorts.deleteTask + TaskItemDeleteClicked title id -> + ( deleteCardRequested title id model + , Cmd.none , Session.NoOp ) TaskItemEditClicked id -> - ( session - , cmdIfHasTask id session InteropPorts.openTaskSourceFile + ( model + , cmdIfHasTask id model InteropPorts.openTaskSourceFile , Session.NoOp ) @@ -109,25 +183,26 @@ update msg session = let timeWithZone : TimeWithZone timeWithZone = - Session.timeWithZone session + Session.timeWithZone (toSession model) toggleCmd : TaskItem -> Cmd Msg toggleCmd taskItem = InteropPorts.rewriteTasks - (Session.dataviewTaskCompletion session) - (Session.globalSettings session |> .taskCompletionFormat) + (Session.dataviewTaskCompletion <| toSession model) + (Session.taskCompletionSettings <| toSession model) timeWithZone (TaskItem.filePath taskItem) (TaskItem.tasksToToggle id timeWithZone taskItem) cmd : Cmd Msg cmd = - session + model + |> toSession |> Session.taskContainingId id |> Maybe.map toggleCmd |> Maybe.withDefault Cmd.none in - ( session + ( model , cmd , Session.NoOp ) @@ -136,44 +211,100 @@ update msg session = let newSession : Session newSession = - Session.updateColumnCollapse columnIndex newState session + Session.updateColumnCollapse columnIndex newState (toSession model) in - ( newSession + ( mapSession (always newSession) model , InteropPorts.updateSettings <| Session.settings newSession , Session.NoOp ) -cmdIfHasTask : String -> Session -> (TaskItemFields -> Cmd b) -> Cmd b -cmdIfHasTask id session cmd = - session +cmdIfHasTask : String -> Model -> (TaskItemFields -> Cmd b) -> Cmd b +cmdIfHasTask id model cmd = + model + |> toSession |> Session.taskFromId id |> Maybe.map TaskItem.fields |> Maybe.map cmd |> Maybe.withDefault Cmd.none -updateBoardOrder : DragTracker -> DragData -> Session -> Session -updateBoardOrder dragTracker { cursor, beacons } session = +updateBoardOrder : DragTracker -> DragData -> Model -> Model +updateBoardOrder dragTracker { cursor, beacons } model = case dragTracker of DragTracker.Dragging clientData _ -> case Rect.closestTo cursor beacons of Nothing -> - session + model Just position -> - Session.moveBoard clientData.uniqueId position session + mapSession (Session.moveBoard clientData.uniqueId position) model _ -> - session + model -- VIEW -view : Session -> Html Msg -view session = +view : Model -> Html Msg +view model = + case model of + ViewingBoard session -> + Html.div [] + [ boardsView session ] + + DeletingCard title cardId session -> + Html.div [] + [ boardsView session + , modalDeleteCardConfirm title cardId + ] + + +modalDeleteCardConfirm : String -> String -> Html Msg +modalDeleteCardConfirm title cardId = + Html.div [ class "modal-container" ] + [ Html.div + [ class "modal-bg" + , style "opacity" "0.85" + ] + [] + , Html.div [ class "modal" ] + [ Html.div + [ class "modal-close-button" + , onClick ModalCloseClicked + ] + [] + , Html.div [ class "modal-title" ] + [ Html.text "Delete Card" ] + , Html.div [ class "modal-content" ] + [ Html.p [ class "mod-warning" ] + [ Html.text <| + "Press Delete to confirm you wish to delete the \"" + ++ title + ++ "\" card. This does not delete the task from your " + ++ "markdown, it encloses it in tags." + ] + ] + , Html.div [ class "modal-button-container" ] + [ Html.button + [ class "mod-warning" + , onClick <| DeleteConfirmed cardId + ] + [ Html.text "Delete" + ] + , Html.button + [ onClick <| ModalCancelClicked ] + [ Html.text "Cancel" + ] + ] + ] + ] + + +boardsView : Session -> Html Msg +boardsView session = if SafeZipper.length (Session.boardConfigs session) == 0 then Html.text "Loading tasks...." @@ -483,7 +614,7 @@ cardView today card = dataTags = card |> Card.allTags - |> TagList.toList + |> TagList.toStrings |> List.map (String.replace "/" "-") |> String.join " " @@ -533,9 +664,9 @@ cardView today card = , notesView (Card.notesId card) |> when (TaskItem.hasNotes taskItem) , Html.div [ class "card-board-card-footer-area" ] - [ taskDueDate (TaskItem.due taskItem) + [ taskDueDate today (TaskItem.due taskItem) |> when (TaskItem.isDated taskItem) - , cardActionButtons taskItemId (Card.editButtonId card) + , cardActionButtons (Card.title card) taskItemId (Card.editButtonId card) ] ] ] @@ -577,25 +708,29 @@ subtaskView ( uniqueId, subtask ) = ] -taskDueDate : Maybe Date -> Html Msg -taskDueDate dueDate = +taskDueDate : Date -> Maybe Date -> Html Msg +taskDueDate today dueDate = Html.div [ class "card-board-card-action-area-due" ] - [ Html.text ("Due: " ++ dueDateString dueDate) + [ Html.text ("Due: " ++ dueDateString today dueDate) ] -dueDateString : Maybe Date -> String -dueDateString dueDate = +dueDateString : Date -> Maybe Date -> String +dueDateString today dueDate = case dueDate of Just date -> - Date.format "E, MMM ddd" date + if Date.year date == Date.year today then + Date.format "E, MMM ddd" date + + else + Date.format "E, MMM ddd y" date Nothing -> "n/a" -cardActionButtons : String -> String -> Html Msg -cardActionButtons taskItemId editButtonId = +cardActionButtons : String -> String -> String -> Html Msg +cardActionButtons title taskItemId editButtonId = Html.div [ class "card-board-card-action-area-buttons" ] [ Html.div [ class "card-board-card-action-area-button" @@ -609,7 +744,7 @@ cardActionButtons taskItemId editButtonId = ] , Html.div [ class "card-board-card-action-area-button" - , onClick <| TaskItemDeleteClicked taskItemId + , onClick <| TaskItemDeleteClicked title taskItemId ] [ FeatherIcons.trash |> FeatherIcons.withSize 1 diff --git a/src/Page/Helper/MultiSelect.elm b/src/Page/Helper/MultiSelect.elm index 26d464c2..030bf7d0 100644 --- a/src/Page/Helper/MultiSelect.elm +++ b/src/Page/Helper/MultiSelect.elm @@ -8,6 +8,7 @@ module Page.Helper.Multiselect exposing , recieveItems , selectedItems , update + , updateGrouper , updateSelectedItems , view ) @@ -146,6 +147,19 @@ itemWasPressed = -- TRANSFORM +mapConfig : (Config msg a -> Config msg a) -> Model msg a -> Model msg a +mapConfig fn model = + case model of + Ready conf selectStatus -> + Ready (fn conf) selectStatus + + SettingItems conf selectStatus -> + SettingItems (fn conf) selectStatus + + ReceivedItems conf selectStatus -> + ReceivedItems (fn conf) selectStatus + + mapStatus : (Status a -> Status a) -> Model msg a -> Model msg a mapStatus transform model = case model of @@ -204,6 +218,11 @@ deleteHighlightedItem model = model +updateGrouper : (List (SelectionItem a) -> List ( String, List (SelectionItem a) )) -> Model msg a -> Model msg a +updateGrouper newGrouper model = + mapConfig (\c -> { c | grouper = newGrouper }) model + + updateSelectedItems : Dict String a -> Model msg a -> Model msg a updateSelectedItems selectedItems_ model = mapStatus (\s -> { s | selectedItems = selectedItems_ }) model diff --git a/src/Page/Settings.elm b/src/Page/Settings.elm index 60f6712b..6abb1f20 100644 --- a/src/Page/Settings.elm +++ b/src/Page/Settings.elm @@ -25,8 +25,10 @@ import Form.Column.Dated exposing (DatedColumnForm) import Form.Columns as ColumnsForm exposing (ColumnsForm) import Form.NewBoard as NewBoardForm exposing (NewBoardForm) import Form.NewColumn as NewColumnForm exposing (NewColumnForm) +import Form.SafeDecoder as SD import Form.Settings as SettingsForm exposing (SettingsForm) import Form.SettingsState as SettingsState exposing (SettingsState) +import GlobalSettings exposing (TaskCompletionSettings) import Html exposing (Attribute, Html) import Html.Attributes exposing (attribute, class, id, placeholder, selected, style, type_, value) import Html.Events exposing (onClick, onInput) @@ -42,6 +44,7 @@ import Settings exposing (Settings) import State exposing (State) import Svg import Svg.Attributes as Svg +import TimeWithZone exposing (TimeWithZone) @@ -134,6 +137,8 @@ type Msg | ScopeSelected String | SelectedDatedColumnRangeType Int String | TaskCompletionFormatSelected String + | ToggleTaskCompletionInLocalTime + | ToggleTaskCompletionShowUtcOffset | ToggleIgnoreFileNameDate | ToggleShowColumnTags | ToggleShowFilteredTags @@ -160,15 +165,37 @@ switchSettingsState fn model = newSettingsState = model.settingsState |> SettingsState.mapBoardBeingEdited (\bc -> { bc | filters = currentSelectedFilters }) + |> SettingsState.mapGlobalSettings (\gs -> { gs | filters = currentSelectedFilters }) |> fn newFilters : Dict String Filter newFilters = - currentFilters <| SettingsState.boardConfigs newSettingsState + case newSettingsState of + SettingsState.EditingGlobalSettings _ -> + newSettingsState + |> SettingsState.settings + |> Settings.globalSettings + |> .filters + |> (\fs -> List.map (\f -> ( Filter.value f, f )) fs) + |> Dict.fromList + + _ -> + currentFilters <| SettingsState.boardConfigs newSettingsState + + newGrouper : List (MultiSelect.SelectionItem Filter) -> List ( String, List (MultiSelect.SelectionItem Filter) ) + newGrouper = + case newSettingsState of + SettingsState.EditingGlobalSettings _ -> + groupedSelectionsWithoutTags + + _ -> + groupedSelections in { model | settingsState = newSettingsState - , multiSelect = MultiSelect.updateSelectedItems newFilters model.multiSelect + , multiSelect = + MultiSelect.updateSelectedItems newFilters model.multiSelect + |> MultiSelect.updateGrouper newGrouper } @@ -315,7 +342,7 @@ update msg model = ) GlobalSettingsClicked -> - mapSettingsState SettingsState.editGlobalSettings model + wrap <| switchSettingsState SettingsState.editGlobalSettings model ModalCancelClicked -> handleClose model @@ -366,6 +393,24 @@ update msg model = model.settingsState } + ToggleTaskCompletionInLocalTime -> + wrap + { model + | settingsState = + SettingsState.mapGlobalSettings + SettingsForm.toggleTaskCompletionInLocalTime + model.settingsState + } + + ToggleTaskCompletionShowUtcOffset -> + wrap + { model + | settingsState = + SettingsState.mapGlobalSettings + SettingsForm.toggleTaskCompletionShowUtcOffset + model.settingsState + } + ToggleIgnoreFileNameDate -> wrap { model @@ -399,6 +444,16 @@ groupedSelections selectionItems = |> ensureAllTypes +groupedSelectionsWithoutTags : List (MultiSelect.SelectionItem Filter) -> List ( String, List (MultiSelect.SelectionItem Filter) ) +groupedSelectionsWithoutTags selectionItems = + selectionItems + |> List.sortBy (\item -> Filter.filterType item.value) + |> LE.groupWhile (\a b -> Filter.filterType a.value == Filter.filterType b.value) + |> List.map (\( i, is ) -> ( Filter.filterType i.value, i :: is )) + |> ensureAllTypes + |> List.filter (\( k, _ ) -> k /= "Tags") + + ensureAllTypes : List ( String, List (MultiSelect.SelectionItem Filter) ) -> List ( String, List (MultiSelect.SelectionItem Filter) ) ensureAllTypes list = let @@ -572,7 +627,12 @@ view model = boardSettingsView settingsForm model.multiSelect dragTracker SettingsState.EditingGlobalSettings settingsForm -> - globalSettingsView (Session.dataviewTaskCompletion <| toSession model) settingsForm dragTracker + globalSettingsView + (Session.dataviewTaskCompletion <| toSession model) + (Session.timeWithZone <| toSession model) + model.multiSelect + settingsForm + dragTracker modalAddBoard : NewBoardForm -> Html Msg @@ -919,38 +979,26 @@ settingsSurroundView currentSection boardConfigForms dragTracker formContents = boardSettingsView : SettingsForm -> MultiSelect.Model Msg Filter -> DragTracker -> Html Msg -boardSettingsView settingsForm multiselect dragTracker = +boardSettingsView settingsForm multiSelect dragTracker = boardSettingsForm (SafeZipper.current <| SettingsForm.boardConfigForms settingsForm) (SafeZipper.currentIndex <| SettingsForm.boardConfigForms settingsForm) (SettingsForm.defaultColumnNames settingsForm) - multiselect + multiSelect dragTracker |> settingsSurroundView Boards settingsForm.boardConfigForms dragTracker -globalSettingsView : DataviewTaskCompletion -> SettingsForm -> DragTracker -> Html Msg -globalSettingsView dataviewTaskCompletion settingsForm dragTracker = +globalSettingsView : DataviewTaskCompletion -> TimeWithZone -> MultiSelect.Model Msg Filter -> SettingsForm -> DragTracker -> Html Msg +globalSettingsView dataviewTaskCompletion timeWithZone multiSelect settingsForm dragTracker = settingsForm - |> globalSettingsForm dataviewTaskCompletion + |> globalSettingsForm dataviewTaskCompletion timeWithZone multiSelect |> settingsSurroundView Options settingsForm.boardConfigForms dragTracker -globalSettingsForm : DataviewTaskCompletion -> SettingsForm -> List (Html Msg) -globalSettingsForm dataviewTaskCompletion settingsForm = +globalSettingsForm : DataviewTaskCompletion -> TimeWithZone -> MultiSelect.Model Msg Filter -> SettingsForm -> List (Html Msg) +globalSettingsForm dataviewTaskCompletion timeWithZone multiSelect settingsForm = let - dataViewExample : String - dataViewExample = - case dataviewTaskCompletion of - DataviewTaskCompletion.NoCompletion -> - "automatic task completion tracking disabled" - - DataviewTaskCompletion.Emoji -> - "✅ 1999-12-31" - - DataviewTaskCompletion.Text t -> - "[" ++ t ++ ":: 1999-12-31]" - ignoreFileNameDatesStyle : String ignoreFileNameDatesStyle = if settingsForm.ignoreFileNameDates then @@ -958,12 +1006,51 @@ globalSettingsForm dataviewTaskCompletion settingsForm = else "" + + taskCompletionInLocalTimeStyle : String + taskCompletionInLocalTimeStyle = + if settingsForm.taskCompletionInLocalTime then + " is-enabled" + + else + "" + + taskCompletionShowUtcOffsetStyle : String + taskCompletionShowUtcOffsetStyle = + if settingsForm.taskCompletionShowUtcOffset then + " is-enabled" + + else + "" + + taskCompletionExample : String + taskCompletionExample = + let + taskCompletionSettings : TaskCompletionSettings + taskCompletionSettings = + settingsForm + |> SD.run SettingsForm.safeDecoder + |> Result.map Settings.globalSettings + |> Result.withDefault GlobalSettings.default + |> GlobalSettings.taskCompletionSettings + in + TimeWithZone.completionString + dataviewTaskCompletion + taskCompletionSettings + timeWithZone + |> (\str -> + if String.length str == 0 then + "[None]" + + else + str + ) in [ Html.div [ class "setting-items-inner" ] ([ Html.div [ class "setting-item setting-item-heading" ] [ Html.div [ class "setting-item-info" ] [ Html.div [ class "setting-item-name" ] - [ Html.text "Daily/Periodic notes compatibility" ] + [ Html.text "Daily/Periodic Notes Compatibility" ] , Html.div [ class "setting-item-description" ] [] ] , Html.div [ class "setting-item-control" ] [] @@ -986,48 +1073,75 @@ globalSettingsForm dataviewTaskCompletion settingsForm = , Html.div [ class "setting-item setting-item-heading" ] [ Html.div [ class "setting-item-info" ] [ Html.div [ class "setting-item-name" ] - [ Html.text "Task completion format" ] + [ Html.text "File/Path Filters" ] , Html.div [ class "setting-item-description" ] [] ] , Html.div [ class "setting-item-control" ] [] ] , Html.div [ class "setting-item" ] [ Html.div [ class "setting-item-info" ] - [ Html.div [ class "setting-item-description" ] - [ Html.text "Format to use when marking tasks as completed:" - , Html.br [] [] - , Html.br [] [] - , Html.strong [] [ Html.text "None" ] - , Html.text ": " - , Html.code [] [ Html.text "no completion date/time will be added" ] - , Html.br [] [] - , Html.strong [] [ Html.text "CardBoard" ] - , Html.text ": " - , Html.code [] [ Html.text "@completed(1999-12-31T23:59:59)" ] - , Html.br [] [] - , Html.strong [] [ Html.text "Dataview" ] - , Html.text ": " - , Html.code [] [ Html.text dataViewExample ] - , Html.i [] [ Html.text " (change via Dataview plugin settings)" ] - , Html.br [] [] - , Html.strong [] [ Html.text "Tasks" ] - , Html.text ": " - , Html.code [] [ Html.text "✅ 1999-12-31" ] - , Html.br [] [] - , Html.br [] [] - , Html.strong [] [ Html.text "For Dataview: " ] - , Html.text "The task related settings in the Dataview plugin (if installed) will be respected" - , Html.text " and should be reflected above." - , Html.i [] [ Html.text " If you change the settings in" ] - , Html.i [] [ Html.text " Dataview you will need to close and re-open the CardBoard view to pick up the changes." ] + [ Html.div [ class "setting-item-name" ] + [ Html.text "Files and paths to ignore" ] + , Html.div [ class "setting-item-description" ] + [ Html.text "Tasks will not be loaded from these. " , Html.br [] [] , Html.br [] [] - , Html.text "When reading tasks, CardBoard understands all these formats." + , Html.span + [ class "mod-warning" ] + [ Html.text "You need to reload Obsidian to see the effect of any changes made to this setting." ] ] ] + , Html.div [ class "setting-item-control" ] + [ MultiSelect.view multiSelect + ] + ] + , Html.div [ class "setting-item setting-item-heading" ] + [ Html.div [ class "setting-item-info" ] + [ Html.div [ class "setting-item-name" ] + [ Html.text "Task Completion" ] + , Html.div [ class "setting-item-description" ] + [ Html.text <| "Current completion string: " ++ taskCompletionExample ] + ] + , Html.div [ class "setting-item-control" ] [] + ] + , Html.div [ class "setting-item" ] + [ Html.div [ class "setting-item-info" ] + [ Html.div [ class "setting-item-name" ] + [ Html.text "Format" ] + , Html.div [ class "setting-item-description" ] [] + ] , Html.div [ class "setting-item-control" ] [ taskCompletionFormatSelect settingsForm.taskCompletionFormat ] ] + , Html.div [ class "setting-item" ] + [ Html.div [ class "setting-item-info" ] + [ Html.div [ class "setting-item-name" ] + [ Html.text "Use local time" ] + , Html.div [ class "setting-item-description" ] + [ Html.text "UTC will be used otherwise." ] + ] + , Html.div [ class "setting-item-control" ] + [ Html.div + [ class <| "checkbox-container" ++ taskCompletionInLocalTimeStyle + , onClick ToggleTaskCompletionInLocalTime + ] + [] + ] + ] + , Html.div [ class "setting-item" ] + [ Html.div [ class "setting-item-info" ] + [ Html.div [ class "setting-item-name" ] + [ Html.text "Include UTC offset" ] + , Html.div [ class "setting-item-description" ] [] + ] + , Html.div [ class "setting-item-control" ] + [ Html.div + [ class <| "checkbox-container" ++ taskCompletionShowUtcOffsetStyle + , onClick ToggleTaskCompletionShowUtcOffset + ] + [] + ] + ] ] ++ columNamesForm settingsForm ) @@ -1168,7 +1282,7 @@ columNamesForm settingsForm = boardSettingsForm : Maybe BoardConfigForm -> Maybe Int -> DefaultColumnNames -> MultiSelect.Model Msg Filter -> DragTracker -> List (Html Msg) -boardSettingsForm boardConfigForm boardIndex defaultColumnNames multiselect dragTracker = +boardSettingsForm boardConfigForm boardIndex defaultColumnNames multiSelect dragTracker = case ( boardConfigForm, boardIndex ) of ( Just configForm, Just _ ) -> let @@ -1243,7 +1357,7 @@ boardSettingsForm boardConfigForm boardIndex defaultColumnNames multiselect drag [ Html.text "Filter tasks by files, paths, and/or tags." ] ] , Html.div [ class "setting-item-control" ] - [ MultiSelect.view multiselect + [ MultiSelect.view multiSelect ] ] , Html.div [ class "setting-item" ] diff --git a/src/ParserHelper.elm b/src/ParserHelper.elm index 171682a6..b2e64c3a 100644 --- a/src/ParserHelper.elm +++ b/src/ParserHelper.elm @@ -171,7 +171,7 @@ timeParser = |> Result.map P.succeed |> Result.withDefault (P.problem "not a valid date") in - P.getChompedString (P.chompWhile <| \c -> Char.isDigit c || c == '-' || c == 'T' || c == ':') + P.getChompedString (P.chompWhile <| \c -> Char.isDigit c || c == '-' || c == 'T' || c == 'Z' || c == ':' || c == '+' || c == '-') |> P.andThen convertToTime diff --git a/src/Session.elm b/src/Session.elm index 8235a91a..9454eaac 100644 --- a/src/Session.elm +++ b/src/Session.elm @@ -21,6 +21,7 @@ module Session exposing , settings , stopTrackingDragable , switchToBoardAt + , taskCompletionSettings , taskContainingId , taskFromId , taskList @@ -43,7 +44,7 @@ import DataviewTaskCompletion exposing (DataviewTaskCompletion) import DragAndDrop.BeaconPosition exposing (BeaconPosition) import DragAndDrop.DragData exposing (DragData) import DragAndDrop.DragTracker as DragTracker exposing (DragTracker) -import GlobalSettings exposing (GlobalSettings) +import GlobalSettings exposing (GlobalSettings, TaskCompletionSettings) import InteropDefinitions import SafeZipper exposing (SafeZipper) import Settings exposing (Settings) @@ -171,6 +172,11 @@ settings (Session config) = config.settings +taskCompletionSettings : Session -> TaskCompletionSettings +taskCompletionSettings = + GlobalSettings.taskCompletionSettings << globalSettings + + taskContainingId : String -> Session -> Maybe TaskItem taskContainingId id (Session config) = case config.taskList of @@ -256,7 +262,7 @@ switchToBoardAt index (Session config) = timeIs : Time.Posix -> Session -> Session timeIs time (Session config) = - Session { config | timeWithZone = TimeWithZone.time time config.timeWithZone } + Session { config | timeWithZone = TimeWithZone.updateTime time config.timeWithZone } timeWithZoneIs : Time.Zone -> Time.Posix -> Session -> Session diff --git a/src/Settings.elm b/src/Settings.elm index f090062b..387768c2 100644 --- a/src/Settings.elm +++ b/src/Settings.elm @@ -77,7 +77,7 @@ defaultColumnNames = currentVersion : Semver.Version currentVersion = - Semver.version 0 11 0 [] [] + Semver.version 0 12 0 [] [] globalSettings : Settings -> GlobalSettings @@ -245,8 +245,11 @@ semverEncoder = versionedSettingsDecoder : TsDecode.AndThenContinuation (String -> TsDecode.Decoder Settings) versionedSettingsDecoder = TsDecode.andThenInit - (\v_0_11_0 v_0_10_0 v_0_9_0 v_0_8_0 v_0_7_0 v_0_6_0 v_0_5_0 v_0_4_0 v_0_3_0 v_0_2_0 v_0_1_0 unsupportedVersion version_ -> + (\v_0_12_0 v_0_11_0 v_0_10_0 v_0_9_0 v_0_8_0 v_0_7_0 v_0_6_0 v_0_5_0 v_0_4_0 v_0_3_0 v_0_2_0 v_0_1_0 unsupportedVersion version_ -> case version_ of + "0.12.0" -> + v_0_12_0 + "0.11.0" -> v_0_11_0 @@ -283,6 +286,7 @@ versionedSettingsDecoder = _ -> unsupportedVersion ) + |> TsDecode.andThenDecoder (TsDecode.field "data" v_0_12_0_Decoder) |> TsDecode.andThenDecoder (TsDecode.field "data" v_0_11_0_Decoder) |> TsDecode.andThenDecoder (TsDecode.field "data" v_0_10_0_Decoder) |> TsDecode.andThenDecoder (TsDecode.field "data" v_0_9_0_Decoder) @@ -297,6 +301,17 @@ versionedSettingsDecoder = |> TsDecode.andThenDecoder (TsDecode.field "data" unsupportedVersionDecoder) +v_0_12_0_Decoder : TsDecode.Decoder Settings +v_0_12_0_Decoder = + TsDecode.succeed Settings + |> TsDecode.andMap + (TsDecode.field "boardConfigs" + (TsDecode.map SafeZipper.fromList (TsDecode.list BoardConfig.decoder_v_0_12_0)) + ) + |> TsDecode.andMap (TsDecode.field "globalSettings" GlobalSettings.v_0_12_0_decoder) + |> TsDecode.andMap (TsDecode.succeed currentVersion) + + v_0_11_0_Decoder : TsDecode.Decoder Settings v_0_11_0_Decoder = TsDecode.succeed Settings @@ -393,7 +408,7 @@ v_0_4_0_Decoder = (TsDecode.field "boardConfigs" (TsDecode.map SafeZipper.fromList (TsDecode.list BoardConfig.decoder_v_0_4_0)) ) - |> TsDecode.andMap (TsDecode.succeed GlobalSettings.default) + |> TsDecode.andMap (TsDecode.succeed globalSettingsDefault) |> TsDecode.andMap (TsDecode.succeed currentVersion) ) |> TsDecode.map setNamesToDefault @@ -406,7 +421,7 @@ v_0_3_0_Decoder = (TsDecode.field "boardConfigs" (TsDecode.map SafeZipper.fromList (TsDecode.list BoardConfig.decoder_v_0_3_0)) ) - |> TsDecode.andMap (TsDecode.succeed GlobalSettings.default) + |> TsDecode.andMap (TsDecode.succeed globalSettingsDefault) |> TsDecode.andMap (TsDecode.succeed currentVersion) ) |> TsDecode.map setNamesToDefault @@ -419,7 +434,7 @@ v_0_2_0_Decoder = (TsDecode.field "boardConfigs" (TsDecode.map SafeZipper.fromList (TsDecode.list BoardConfig.decoder_v_0_2_0)) ) - |> TsDecode.andMap (TsDecode.succeed GlobalSettings.default) + |> TsDecode.andMap (TsDecode.succeed globalSettingsDefault) |> TsDecode.andMap (TsDecode.succeed currentVersion) ) |> TsDecode.map setNamesToDefault @@ -432,12 +447,23 @@ v_0_1_0_Decoder = (TsDecode.field "boardConfigs" (TsDecode.map SafeZipper.fromList (TsDecode.list BoardConfig.decoder_v_0_1_0)) ) - |> TsDecode.andMap (TsDecode.succeed GlobalSettings.default) + |> TsDecode.andMap (TsDecode.succeed globalSettingsDefault) |> TsDecode.andMap (TsDecode.succeed currentVersion) ) |> TsDecode.map setNamesToDefault +globalSettingsDefault : GlobalSettings +globalSettingsDefault = + { defaultColumnNames = DefaultColumnNames.default + , filters = [] + , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False + } + + unsupportedVersionDecoder : TsDecode.Decoder Settings unsupportedVersionDecoder = TsDecode.fail "Unsupported settings file version" diff --git a/src/Tag.elm b/src/Tag.elm index 159c7578..2aeada77 100644 --- a/src/Tag.elm +++ b/src/Tag.elm @@ -2,6 +2,7 @@ module Tag exposing ( Tag , containsInvalidCharacters , equals + , matches , parser , startsWith , toString @@ -48,6 +49,20 @@ equals checkString (Tag tagString) = checkString == tagString +matches : String -> Tag -> Bool +matches checkString (Tag tagString) = + let + exactMatch : String -> String -> Bool + exactMatch check tag = + if String.endsWith "/" check then + String.startsWith check tag || (tag == String.dropRight 1 check) + + else + tag == check + in + exactMatch (String.toLower checkString) (String.toLower tagString) + + startsWith : String -> Tag -> Bool startsWith substring (Tag tagString) = String.startsWith substring tagString diff --git a/src/TagList.elm b/src/TagList.elm index eb71233a..95ca4a54 100644 --- a/src/TagList.elm +++ b/src/TagList.elm @@ -10,8 +10,8 @@ module TagList exposing , fromList , isEmpty , sort - , toList , toString + , toStrings , unique ) @@ -85,17 +85,7 @@ filter test (TagList ts) = containsTagMatching : String -> TagList -> Bool containsTagMatching candidate = - let - matches : String -> Bool - matches t = - if String.endsWith "/" candidate then - String.startsWith (String.toLower candidate) (String.toLower t) - || (String.toLower t == String.dropRight 1 (String.toLower candidate)) - - else - String.toLower t == String.toLower candidate - in - List.any matches << toList + List.any (Tag.matches candidate) << toTags containsTagMatchingOneOf : List String -> TagList -> Bool @@ -109,7 +99,7 @@ containsTagOtherThanThese candidates tagList = fromTagList : Set String fromTagList = tagList - |> toList + |> toStrings |> Set.fromList fromCandidates : Set String @@ -127,7 +117,7 @@ isEmpty (TagList ts) = unique : TagList -> TagList unique = - fromList << LE.uniqueBy String.toLower << toList + fromList << LE.uniqueBy String.toLower << toStrings @@ -136,7 +126,7 @@ unique = sort : TagList -> TagList sort = - fromList << List.sort << toList + fromList << List.sort << toStrings @@ -145,9 +135,18 @@ sort = toString : TagList -> String toString = - String.join " " << List.map (String.append "#") << toList + String.join " " << List.map (String.append "#") << toStrings -toList : TagList -> List String -toList (TagList ts) = +toStrings : TagList -> List String +toStrings (TagList ts) = List.map Tag.toString ts + + + +-- PRIVATE + + +toTags : TagList -> List Tag +toTags (TagList ts) = + ts diff --git a/src/TaskItem.elm b/src/TaskItem.elm index 420a9b19..69ec025b 100644 --- a/src/TaskItem.elm +++ b/src/TaskItem.elm @@ -5,26 +5,23 @@ module TaskItem exposing , TaskItem , TaskItemFields , allSubtasksWithMatchingTagCompleted + , asSingleTaskItems , completedPosix , completion , containsId - , descendantTaskHasThisTag , descendantTasks , due , dueRataDie , dummy , fields , filePath - , hasAnyIncompleteSubtasksWithTagsOtherThanThese - , hasIncompleteTaskWithThisTag , hasNotes - , hasOneOfTheTags , hasSubtasks , hasTags - , hasTaskWithTagOtherThanThese , hasThisTag , hasTopLevelTags , id + , isAllowed , isCompleted , isDated , isFromFile @@ -33,6 +30,7 @@ module TaskItem exposing , originalText , parser , removeFileNameDate + , removeMatchingTags , removeTags , tags , tasksToToggle @@ -40,7 +38,6 @@ module TaskItem exposing , titleWithTags , toToggledString , topLevelTags - , topLevelTaskHasThisTag , updateFilePath ) @@ -49,8 +46,9 @@ import DataviewTaskCompletion exposing (DataviewTaskCompletion) import Date exposing (Date) import DueDate exposing (DueDate) import FNV1a -import GlobalSettings exposing (TaskCompletionFormat) -import Iso8601 +import Filter exposing (Filter, Scope) +import GlobalSettings exposing (TaskCompletionSettings) +import List.Extra as LE import Maybe.Extra as ME import ObsidianTasksDate import Parser as P exposing ((|.), (|=), Parser) @@ -61,6 +59,7 @@ import Tag exposing (Tag) import TagList exposing (TagList) import TaskPaperTag import Time +import TimeWithZone exposing (TimeWithZone) @@ -153,6 +152,11 @@ allSubtasksWithMatchingTagCompleted tagToMatch taskItem = List.all isCompleted matchingSubtasks +asSingleTaskItems : TaskItem -> List TaskItem +asSingleTaskItems ((TaskItem fields_ _) as taskItem) = + TaskItem fields_ [] :: descendantTasks taskItem + + completedPosix : TaskItem -> Int completedPosix ((TaskItem _ subtasks_) as taskItem) = let @@ -199,20 +203,6 @@ descendantTasks (TaskItem _ subtasks_) = List.map (\s -> TaskItem s []) subtasks_ -descendantTaskHasThisTag : String -> TaskItem -> Bool -descendantTaskHasThisTag tagToMatch = - let - descendantTasksTags : TaskItem -> TagList - descendantTasksTags taskItem = - descendantTasks taskItem - |> List.map (fields >> .tags) - |> List.foldl TagList.append TagList.empty - |> TagList.unique - |> TagList.sort - in - TagList.containsTagMatching tagToMatch << descendantTasksTags - - due : TaskItem -> Maybe Date due (TaskItem fields_ _) = case fields_.dueTag of @@ -246,33 +236,6 @@ filePath = .filePath << fields -hasAnyIncompleteSubtasksWithTagsOtherThanThese : List String -> TaskItem -> Bool -hasAnyIncompleteSubtasksWithTagsOtherThanThese tagsToMatch taskItem = - let - subtasksWithTagsOtherThanThese : List TaskItem - subtasksWithTagsOtherThanThese = - taskItem - |> descendantTasks - |> List.filter (hasTagOtherThanThese tagsToMatch) - in - case subtasksWithTagsOtherThanThese of - [] -> - False - - matchingSubtasks -> - List.any (not << isCompleted) matchingSubtasks - - -hasIncompleteTaskWithThisTag : String -> TaskItem -> Bool -hasIncompleteTaskWithThisTag tagToMatch taskItem = - let - isIncompleteWithMatchingTag : TaskItem -> Bool - isIncompleteWithMatchingTag ti = - TagList.containsTagMatching tagToMatch (topLevelTags ti) && not (isCompleted ti) - in - List.any isIncompleteWithMatchingTag (taskItem :: descendantTasks taskItem) - - hasNotes : TaskItem -> Bool hasNotes = not << String.isEmpty << .notes << fields @@ -283,23 +246,11 @@ hasTags = not << TagList.isEmpty << tags -hasTaskWithTagOtherThanThese : List String -> TaskItem -> Bool -hasTaskWithTagOtherThanThese tagsToMatch taskItem = - (taskItem :: descendantTasks taskItem) - |> List.filter hasTopLevelTags - |> List.any (hasAtLeastOneTagOtherThanThese tagsToMatch) - - hasTopLevelTags : TaskItem -> Bool hasTopLevelTags = not << TagList.isEmpty << topLevelTags -hasOneOfTheTags : List String -> TaskItem -> Bool -hasOneOfTheTags tagsToMatch taskItem = - List.any (\t -> hasThisTag t taskItem) tagsToMatch - - hasThisTag : String -> TaskItem -> Bool hasThisTag tagToMatch = TagList.containsTagMatching tagToMatch << tags @@ -317,6 +268,27 @@ id (TaskItem fields_ _) = ++ String.fromInt fields_.lineNumber +isAllowed : Scope -> TaskItem -> Filter -> Bool +isAllowed scope taskItem filter = + case filter of + Filter.FileFilter filePath_ -> + isFromFile filePath_ taskItem + + Filter.PathFilter path -> + fileIsFromPath (filePath taskItem) path + + Filter.TagFilter tag -> + case scope of + Filter.TopLevelOnly -> + topLevelTaskHasThisTag tag taskItem + + Filter.SubTasksOnly -> + descendantTaskHasThisTag tag taskItem + + Filter.Both -> + hasThisTag tag taskItem + + isCompleted : TaskItem -> Bool isCompleted (TaskItem fields_ _) = case fields_.completion of @@ -454,16 +426,6 @@ titleWithTags taskItem = |> String.join " " -topLevelTaskHasThisTag : String -> TaskItem -> Bool -topLevelTaskHasThisTag tagToMatch = - let - topLevelTasksTags : TaskItem -> TagList - topLevelTasksTags (TaskItem fields_ _) = - fields_.tags - in - TagList.containsTagMatching tagToMatch << topLevelTasksTags - - -- MODIFICATION @@ -473,6 +435,16 @@ removeFileNameDate (TaskItem fields_ subtasks_) = TaskItem { fields_ | dueFile = Nothing } subtasks_ +removeMatchingTags : String -> TaskItem -> TaskItem +removeMatchingTags tagToRemove taskItem = + let + remover : TagList -> TagList + remover tagList = + TagList.filter (not << Tag.matches tagToRemove) tagList + in + mapTags remover taskItem + + removeTags : List String -> TaskItem -> TaskItem removeTags toRemove (TaskItem fields_ subtasks_) = let @@ -527,8 +499,8 @@ parser dataviewTaskCompletion pathToFile fileDate frontMatterTags bodyOffset = -- CONVERT -toToggledString : DataviewTaskCompletion -> TaskCompletionFormat -> { a | time : Time.Posix } -> TaskItem -> String -toToggledString dataviewTaskCompletion taskCompletionFormat timeWithZone ((TaskItem fields_ _) as taskItem) = +toToggledString : DataviewTaskCompletion -> TaskCompletionSettings -> TimeWithZone -> TaskItem -> String +toToggledString dataviewTaskCompletion taskCompletionSettings timeWithZone ((TaskItem fields_ _) as taskItem) = let blockLinkRegex : Regex blockLinkRegex = @@ -544,33 +516,17 @@ toToggledString dataviewTaskCompletion taskCompletionFormat timeWithZone ((TaskI completionTag t_ = case completion t_ of Incomplete -> - let - completionString : String - completionString = - timeWithZone.time - |> Iso8601.fromTime - |> String.left 19 - in - case taskCompletionFormat of - GlobalSettings.NoCompletion -> - "" - - GlobalSettings.ObsidianCardBoard -> - " @completed(" ++ completionString ++ ")" - - GlobalSettings.ObsidianDataview -> - case dataviewTaskCompletion of - DataviewTaskCompletion.NoCompletion -> + TimeWithZone.completionString + dataviewTaskCompletion + taskCompletionSettings + timeWithZone + |> (\str -> + if String.length str == 0 then "" - DataviewTaskCompletion.Emoji -> - " ✅ " ++ String.left 10 completionString - - DataviewTaskCompletion.Text t -> - " [" ++ t ++ ":: " ++ String.left 10 completionString ++ "]" - - GlobalSettings.ObsidianTasks -> - " ✅ " ++ String.left 10 completionString + else + " " ++ str + ) _ -> "" @@ -612,7 +568,7 @@ toToggledString dataviewTaskCompletion taskCompletionFormat timeWithZone ((TaskI DataviewTaskCompletion.Text t -> regexReplacer (" \\[" ++ t ++ ":: \\d{4}-\\d{2}-\\d{2}\\]") (\_ -> "") in - regexReplacer " @completed\\(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\)" (\_ -> "") + regexReplacer " @completed\\(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:(?:[+-]\\d{2}:\\d{2})|Z){0,1}\\)" (\_ -> "") >> regexReplacer " ✅ \\d{4}-\\d{2}-\\d{2}" (\_ -> "") >> dataviewRemover @@ -725,19 +681,38 @@ fileDateParser fileDate = |> P.succeed -hasAtLeastOneTagOtherThanThese : List String -> TaskItem -> Bool -hasAtLeastOneTagOtherThanThese tagsToMatch taskItem = - taskItem - |> fields - |> .tags - |> TagList.containsTagOtherThanThese tagsToMatch - +fileIsFromPath : String -> String -> Bool +fileIsFromPath file path = + let + pathComponents : List String + pathComponents = + path + |> String.replace "\\" "/" + |> String.split "/" + |> List.filter (not << String.isEmpty) + + filePathComponents : List String + filePathComponents = + file + |> String.replace "\\" "/" + |> String.split "/" + |> List.reverse + |> List.drop 1 + |> List.reverse + |> List.filter (not << String.isEmpty) + + isComponentMatching : Int -> String -> Bool + isComponentMatching index pathComponent = + case LE.getAt index filePathComponents of + Nothing -> + False -hasTagOtherThanThese : List String -> TaskItem -> Bool -hasTagOtherThanThese tagsToMatch taskItem = - fields taskItem - |> .tags - |> TagList.containsTagOtherThanThese tagsToMatch + Just filePathComponent -> + filePathComponent == pathComponent + in + pathComponents + |> List.indexedMap isComponentMatching + |> List.all identity indentedItemParser : DataviewTaskCompletion -> String -> Maybe String -> TagList -> Int -> Parser IndentedItem @@ -905,3 +880,41 @@ tokenParser dataviewTaskCompletion = , P.succeed Word |= ParserHelper.wordParser ] + + + +-- PRIVATE + + +descendantTaskHasThisTag : String -> TaskItem -> Bool +descendantTaskHasThisTag tagToMatch = + let + descendantTasksTags : TaskItem -> TagList + descendantTasksTags taskItem = + descendantTasks taskItem + |> List.map (fields >> .tags) + |> List.foldl TagList.append TagList.empty + |> TagList.unique + |> TagList.sort + in + TagList.containsTagMatching tagToMatch << descendantTasksTags + + +mapFields : (TaskItemFields -> TaskItemFields) -> TaskItem -> TaskItem +mapFields fn (TaskItem fields_ subtasks_) = + TaskItem (fn fields_) subtasks_ + + +mapTags : (TagList -> TagList) -> TaskItem -> TaskItem +mapTags fn taskItem = + mapFields (\fs -> { fs | tags = fn fs.tags }) taskItem + + +topLevelTaskHasThisTag : String -> TaskItem -> Bool +topLevelTaskHasThisTag tagToMatch = + let + topLevelTasksTags : TaskItem -> TagList + topLevelTasksTags (TaskItem fields_ _) = + fields_.tags + in + TagList.containsTagMatching tagToMatch << topLevelTasksTags diff --git a/src/TaskList.elm b/src/TaskList.elm index a5b61f2d..9c5f0be3 100644 --- a/src/TaskList.elm +++ b/src/TaskList.elm @@ -10,7 +10,6 @@ module TaskList exposing , map , parser , removeForFile - , removeTags , replaceForFile , taskContainingId , taskFromId @@ -118,11 +117,6 @@ removeForFile filePath = TaskList << itemsNotFromFile filePath << topLevelTasks -removeTags : List String -> TaskList -> TaskList -removeTags tags = - map (TaskItem.removeTags tags) - - -- UTILITIES diff --git a/src/TimeWithZone.elm b/src/TimeWithZone.elm index aaea9456..700c249f 100644 --- a/src/TimeWithZone.elm +++ b/src/TimeWithZone.elm @@ -1,24 +1,191 @@ module TimeWithZone exposing ( TimeWithZone - , time + , completionString , toDate + , toString + , updateTime ) +import DataviewTaskCompletion exposing (DataviewTaskCompletion) import Date exposing (Date) -import Time +import GlobalSettings exposing (TaskCompletionSettings) +import Time exposing (Zone) +import Time.Extra as TE + + + +-- TYPES type alias TimeWithZone = { time : Time.Posix - , zone : Time.Zone + , zone : Zone } -time : Time.Posix -> TimeWithZone -> TimeWithZone -time t timeWithZone = - { timeWithZone | time = t } + +-- INFO + + +completionString : DataviewTaskCompletion -> TaskCompletionSettings -> TimeWithZone -> String +completionString dataviewTaskCompletion taskCompletionSettings timeWithZone = + let + timeStamp : String + timeStamp = + toString taskCompletionSettings timeWithZone + in + case taskCompletionSettings.format of + GlobalSettings.NoCompletion -> + "" + + GlobalSettings.ObsidianCardBoard -> + "@completed(" ++ timeStamp ++ ")" + + GlobalSettings.ObsidianDataview -> + case dataviewTaskCompletion of + DataviewTaskCompletion.NoCompletion -> + "" + + DataviewTaskCompletion.Emoji -> + "✅ " ++ String.left 10 timeStamp + + DataviewTaskCompletion.Text t -> + "[" ++ t ++ ":: " ++ String.left 10 timeStamp ++ "]" + + GlobalSettings.ObsidianTasks -> + "✅ " ++ String.left 10 timeStamp toDate : TimeWithZone -> Date toDate timeWithZone = Date.fromPosix timeWithZone.zone timeWithZone.time + + +toString : { a | inLocalTime : Bool, showUtcOffset : Bool } -> TimeWithZone -> String +toString settings timeWithZone = + let + zoneToUse : Zone + zoneToUse = + if settings.inLocalTime then + timeWithZone.zone + + else + Time.utc + in + toPaddedString 4 (Time.toYear zoneToUse timeWithZone.time) + ++ "-" + -- MM + ++ toPaddedString 2 (fromMonth (Time.toMonth zoneToUse timeWithZone.time)) + ++ "-" + -- DD + ++ toPaddedString 2 (Time.toDay zoneToUse timeWithZone.time) + ++ "T" + -- HH + ++ toPaddedString 2 (Time.toHour zoneToUse timeWithZone.time) + ++ ":" + -- mm + ++ toPaddedString 2 (Time.toMinute zoneToUse timeWithZone.time) + ++ ":" + -- ss + ++ toPaddedString 2 (Time.toSecond zoneToUse timeWithZone.time) + ++ offsetString settings timeWithZone + + + +-- MODIFICATION + + +updateTime : Time.Posix -> TimeWithZone -> TimeWithZone +updateTime t timeWithZone = + { timeWithZone | time = t } + + + +-- PRIVATE + + +fromMonth : Time.Month -> Int +fromMonth month = + case month of + Time.Jan -> + 1 + + Time.Feb -> + 2 + + Time.Mar -> + 3 + + Time.Apr -> + 4 + + Time.May -> + 5 + + Time.Jun -> + 6 + + Time.Jul -> + 7 + + Time.Aug -> + 8 + + Time.Sep -> + 9 + + Time.Oct -> + 10 + + Time.Nov -> + 11 + + Time.Dec -> + 12 + + +offsetString : { a | inLocalTime : Bool, showUtcOffset : Bool } -> TimeWithZone -> String +offsetString settings timeWithZone = + case ( settings.inLocalTime, settings.showUtcOffset ) of + ( False, False ) -> + "" + + ( False, True ) -> + "Z" + + ( True, False ) -> + "" + + ( True, True ) -> + let + offset : Int + offset = + TE.toOffset timeWithZone.zone timeWithZone.time + in + offsetSign offset ++ offsetValue offset + + +offsetSign : Int -> String +offsetSign offset = + if offset >= 0 then + "+" + + else + "-" + + +offsetValue : Int -> String +offsetValue offset = + let + hours : Int + hours = + abs offset // 60 + in + toPaddedString 2 hours + ++ ":" + ++ toPaddedString 2 (abs offset - (hours * 60)) + + +toPaddedString : Int -> Int -> String +toPaddedString digits time_ = + String.padLeft digits '0' (String.fromInt time_) diff --git a/styles.css b/styles.css index 061610b0..3a3dc645 100644 --- a/styles.css +++ b/styles.css @@ -24,7 +24,7 @@ .card-board-view { height: 100%; background-color: var(--background-primary); - font-size: var(--font-normal); + font-size: var(--font-text-size); } .mod-macos.is-hidden-frameless:not(.is-popout-window) .workspace .workspace-tabs.mod-top-right-space .card-board-view .workspace-tab-header-container { @@ -212,6 +212,7 @@ ul.card-board-column-list > li.card-board-card::before { display: grid; grid: "mark contents" / 5px auto; + font-family: var(--font-text); } .card-board-card-highlight-area { @@ -538,14 +539,39 @@ ul.card-board-column-list > li.card-board-card::before { vertical-align: middle; } + +.card-board-view .vertical-tab-content { + position: relative; +} + +.card-board-view .modal-close-button { + z-index: 1; +} + .card-board-view .suggestion-container { + position: absolute; display: grid; grid-auto-flow: row; grid-gap: 0.5em; + overflow: auto; padding: 5px 8px; font-size: var(--font-small); text-align: left; line-height: 1em; + max-height: 400px; +} + +.card-board-view .suggestion-container::-webkit-scrollbar { + width: 8px; +} + +.card-board-view .suggestion-container::-webkit-scrollbar-track { + background: #f1f1f1; +} + +.card-board-view .suggestion-container::-webkit-scrollbar-thumb { + background: #888; + border-radius: 4px; } .card-board-view .suggestion-section { diff --git a/tests/BoardConfigTests.elm b/tests/BoardConfigTests.elm index eabe3adb..2f98ba59 100644 --- a/tests/BoardConfigTests.elm +++ b/tests/BoardConfigTests.elm @@ -84,7 +84,7 @@ encodeDecode = BoardConfigHelpers.exampleBoardConfig |> TsEncode.runExample BoardConfig.encoder |> .output - |> DecodeHelpers.runDecoder BoardConfig.decoder_v_0_11_0 + |> DecodeHelpers.runDecoder BoardConfig.decoder_v_0_12_0 |> .decoded |> Expect.equal (Ok BoardConfigHelpers.exampleBoardConfig) ] diff --git a/tests/CardTests.elm b/tests/CardTests.elm index 4a1bf8b7..8ec512fb 100644 --- a/tests/CardTests.elm +++ b/tests/CardTests.elm @@ -29,6 +29,7 @@ suite = , notesId , tagsId , taskItemId + , title ] @@ -46,14 +47,14 @@ allTags = taskItemWithTags |> Maybe.map (Card.fromTaskItem "a_prefix" []) |> Maybe.map Card.allTags - |> Maybe.map TagList.toList + |> Maybe.map TagList.toStrings |> Expect.equal (Just [ "arg", "bar", "baz/boo" ]) , test "does not remove any tags even if the match the remove list" <| \() -> taskItemWithTags |> Maybe.map (Card.fromTaskItem "a_prefix" [ "bar" ]) |> Maybe.map Card.allTags - |> Maybe.map TagList.toList + |> Maybe.map TagList.toStrings |> Expect.equal (Just [ "arg", "bar", "baz/boo" ]) ] @@ -95,14 +96,14 @@ displayTags = taskItemWithTags |> Maybe.map (Card.fromTaskItem "a_prefix" []) |> Maybe.map Card.displayTags - |> Maybe.map TagList.toList + |> Maybe.map TagList.toStrings |> Expect.equal (Just [ "arg", "bar", "baz/boo" ]) , test "removes any tags matching the remove list" <| \() -> taskItemWithTags |> Maybe.map (Card.fromTaskItem "a_prefix" [ "bar" ]) |> Maybe.map Card.displayTags - |> Maybe.map TagList.toList + |> Maybe.map TagList.toStrings |> Expect.equal (Just [ "arg", "baz/boo" ]) ] @@ -288,6 +289,18 @@ taskItemId = ] +title : Test +title = + describe "title" + [ test "returns the title of the TaskItem" <| + \() -> + taskItem + |> Maybe.map (Card.fromTaskItem "" []) + |> Maybe.map Card.title + |> Expect.equal (Just "foo") + ] + + -- HELPERS diff --git a/tests/Column/OtherTagsTests.elm b/tests/Column/OtherTagsTests.elm index cbdbe2fb..516e306f 100644 --- a/tests/Column/OtherTagsTests.elm +++ b/tests/Column/OtherTagsTests.elm @@ -33,41 +33,73 @@ suite = addTaskItem : Test addTaskItem = describe "addTaskItem" - [ test "places an incomplete tagged card when no otherTags have been configured" <| - \() -> - OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag" ] - |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag") - |> Tuple.mapFirst OtherTagsColumn.toList - |> Tuple.mapFirst (List.map TaskItem.title) - |> Expect.equal ( [ "foo" ], PlacementResult.Placed ) - , test "DOES NOT place an incomplete tagged card when otherTags INCLUDES the current one" <| - \() -> - OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag", "aTag" ] - |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag") - |> Tuple.mapFirst OtherTagsColumn.toList - |> Tuple.mapFirst (List.map TaskItem.title) - |> Expect.equal ( [], PlacementResult.DoesNotBelong ) - , test "DOES NOT place a completed tagged card when no otherTags have been configured" <| - \() -> - OtherTagsColumn.init "" [] - |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") - |> Tuple.mapFirst OtherTagsColumn.toList - |> Tuple.mapFirst (List.map TaskItem.title) - |> Expect.equal ( [], PlacementResult.CompletedInThisColumn ) - , test "DOES NOT place a completed tagged card when otherTags which don't include the current one have been configured" <| - \() -> - OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag" ] - |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") - |> Tuple.mapFirst OtherTagsColumn.toList - |> Tuple.mapFirst (List.map TaskItem.title) - |> Expect.equal ( [], PlacementResult.CompletedInThisColumn ) - , test "DOES NOT place a completed tagged card when otherTags INCLUDES the current one" <| - \() -> - OtherTagsColumn.init "" [ "aTa", "aTag", "bTag", "aTagger", "aTag/subtag", "aTag" ] - |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") - |> Tuple.mapFirst OtherTagsColumn.toList - |> Tuple.mapFirst (List.map TaskItem.title) - |> Expect.equal ( [], PlacementResult.DoesNotBelong ) + [ describe "incomplete tasks" + [ test "places a tagged card when NO otherTags have been configured" <| + \() -> + OtherTagsColumn.init "" [] + |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [ "foo" ], PlacementResult.Placed ) + , test "places a tagged card when NON-MATCHING otherTags have been configured" <| + \() -> + OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag" ] + |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [ "foo" ], PlacementResult.Placed ) + , test "DOES NOT place an UN-tagged card when no otherTags have been configured" <| + \() -> + OtherTagsColumn.init "" [] + |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.DoesNotBelong ) + , test "DOES NOT place a tagged card when otherTags INCLUDES the current one" <| + \() -> + OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag", "aTag" ] + |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.DoesNotBelong ) + , test "DOES NOT place a tagged card when included in another column as a sub-tag" <| + \() -> + OtherTagsColumn.init "" [ "aTag/" ] + |> OtherTagsColumn.addTaskItem (taskItem "- [ ] foo #aTag/foo") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.DoesNotBelong ) + ] + , describe "completed tasks" + [ test "CompletedInThisColumn a tagged card when no otherTags have been configured" <| + \() -> + OtherTagsColumn.init "" [] + |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.CompletedInThisColumn ) + , test "CompletedInThisColumn a tagged card when otherTags which don't include the current one have been configured" <| + \() -> + OtherTagsColumn.init "" [ "aTa", "bTag", "aTagger", "aTag/subtag" ] + |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.CompletedInThisColumn ) + , test "CompletedInThisColumn a completed tagged card with incomplete tagged subtasks" <| + \() -> + OtherTagsColumn.init "" [] + |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag\n - [ ] bar #bTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.CompletedInThisColumn ) + , test "DoesNotBelong a tagged card when otherTags INCLUDES the current one" <| + \() -> + OtherTagsColumn.init "" [ "aTa", "aTag", "bTag", "aTagger", "aTag/subtag", "aTag" ] + |> OtherTagsColumn.addTaskItem (taskItem "- [x] foo #aTag") + |> Tuple.mapFirst OtherTagsColumn.toList + |> Tuple.mapFirst (List.map TaskItem.title) + |> Expect.equal ( [], PlacementResult.DoesNotBelong ) + ] ] diff --git a/tests/DefaultColumnNamesTests.elm b/tests/DefaultColumnNamesTests.elm index 525b9d89..cfda9bf5 100644 --- a/tests/DefaultColumnNamesTests.elm +++ b/tests/DefaultColumnNamesTests.elm @@ -23,13 +23,13 @@ encodeDecode = DefaultColumnNames.default |> TsEncode.runExample DefaultColumnNames.encoder |> .output - |> DecodeHelpers.runDecoder DefaultColumnNames.v_0_11_0_decoder + |> DecodeHelpers.runDecoder DefaultColumnNames.v_0_12_0_decoder |> .decoded |> Expect.equal (Ok DefaultColumnNames.default) , test "can decode an encoded non default back to the original" <| \() -> exampleColumnNames - |> DecodeHelpers.runDecoder DefaultColumnNames.v_0_11_0_decoder + |> DecodeHelpers.runDecoder DefaultColumnNames.v_0_12_0_decoder |> .decoded |> Result.withDefault DefaultColumnNames.default |> TsEncode.runExample DefaultColumnNames.encoder diff --git a/tests/FilterTests.elm b/tests/FilterTests.elm index f0368480..40e8f26f 100644 --- a/tests/FilterTests.elm +++ b/tests/FilterTests.elm @@ -4,7 +4,6 @@ import Expect import Filter import Helpers.DecodeHelpers as DecodeHelpers import Helpers.FilterHelpers as FilterHelpers -import Helpers.TaskItemHelpers as TaskItemHelpers import Test exposing (..) import TsJson.Decode as TsDecode import TsJson.Encode as TsEncode @@ -18,7 +17,6 @@ suite = , encodeDecode , filterType , filterTypes - , isAllowed , ofType , polarityFromString , updatePath @@ -161,137 +159,6 @@ filterTypes = ] -isAllowed : Test -isAllowed = - describe "isAllowed" - [ test "returns True for a matching file filter" <| - \() -> - FilterHelpers.fileFilter "a/b/c.ext" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "a/b/c.ext") - |> Expect.equal True - , test "returns False for a non-matching file filter" <| - \() -> - FilterHelpers.fileFilter "a/b/c.diff" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "a/b/c.ext") - |> Expect.equal False - , test "returns True for a matching windows path filter for the full path" <| - \() -> - FilterHelpers.pathFilter "aa\\\\bb" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal True - , test "returns True for a matching windows path filter with a trailing \\" <| - \() -> - FilterHelpers.pathFilter "aa\\\\bb\\\\" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal True - , test "returns True for a matching windows path filter for the first part of the path" <| - \() -> - FilterHelpers.pathFilter "aa" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal True - , test "returns True for a matching windows path filter of \\" <| - \() -> - FilterHelpers.pathFilter "\\\\" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal True - , test "returns True for an empty windows path filter" <| - \() -> - FilterHelpers.pathFilter "" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal True - , test "returns False if the windows path filter only contains a part of the last path componant" <| - \() -> - FilterHelpers.pathFilter "aa\\\\b" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal False - , test "returns False if the windows path filter contains the file name" <| - \() -> - FilterHelpers.pathFilter "aa\\\\bb\\\\c" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal False - , test "returns False if the windows path filter contains the file name & extension" <| - \() -> - FilterHelpers.pathFilter "aa\\\\bb\\\\c.ext" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") - |> Expect.equal False - , test "returns True for a matching path filter for the full path" <| - \() -> - FilterHelpers.pathFilter "aa/bb" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal True - , test "returns True for a matching path filter with a trailing /" <| - \() -> - FilterHelpers.pathFilter "aa/bb/" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal True - , test "returns True for a matching path filter for the first part of the path" <| - \() -> - FilterHelpers.pathFilter "aa" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal True - , test "returns True for a matching path filter of /" <| - \() -> - FilterHelpers.pathFilter "/" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal True - , test "returns True for an empty path filter" <| - \() -> - FilterHelpers.pathFilter "" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal True - , test "returns False if the path filter only contains a part of the last path componant" <| - \() -> - FilterHelpers.pathFilter "aa/b" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal False - , test "returns False if the path filter contains the file name" <| - \() -> - FilterHelpers.pathFilter "aa/bb/c" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal False - , test "returns False if the path filter contains the file name & extension" <| - \() -> - FilterHelpers.pathFilter "aa/bb/c.ext" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") - |> Expect.equal False - , test "returns True for a matching top level tag when the scope is Both" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") - |> Expect.equal True - , test "returns True for a matching top level tag when the scope is TopLevelOnly" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.TopLevelOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") - |> Expect.equal True - , test "returns False for a matching top level tag when the scope is SubTasksOnly" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.SubTasksOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") - |> Expect.equal False - , test "returns True for a matching sub task tag when the scope is Both" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") - |> Expect.equal True - , test "returns False for a matching sub task tag when the scope is TopLevelOnly" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.TopLevelOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") - |> Expect.equal False - , test "returns True for a matching sub task tag when the scope is SubTasksOnly" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.SubTasksOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") - |> Expect.equal True - , test "returns False for a non-matching tag filter" <| - \() -> - FilterHelpers.tagFilter "taga" - |> Filter.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo #tagb tagc" "") - |> Expect.equal False - ] - - ofType : Test ofType = describe "ofType" diff --git a/tests/Form/SettingsStateTests.elm b/tests/Form/SettingsStateTests.elm index 1d5ed07f..561dfe47 100644 --- a/tests/Form/SettingsStateTests.elm +++ b/tests/Form/SettingsStateTests.elm @@ -1037,10 +1037,13 @@ exampleSettingsForm : SettingsForm exampleSettingsForm = { boardConfigForms = SafeZipper.empty , completed = "" + , filters = [] , future = "" , ignoreFileNameDates = False , otherTags = "" , taskCompletionFormat = "" + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False , today = "" , tomorrow = "" , undated = "" diff --git a/tests/Form/SettingsTests.elm b/tests/Form/SettingsTests.elm index dc9d5b23..a37e54af 100644 --- a/tests/Form/SettingsTests.elm +++ b/tests/Form/SettingsTests.elm @@ -29,6 +29,8 @@ suite = , moveBoard , safeDecoder , toggleIgnoreFileNameDate + , toggleTaskCompletionInLocalTime + , toggleTaskCompletionShowUtcOffset , updateDefaultColumnName , updateTaskCompletionFormat ] @@ -377,6 +379,34 @@ safeDecoder = |> Result.map Settings.globalSettings |> Result.map .taskCompletionFormat |> Expect.equal (Ok <| GlobalSettings.ObsidianCardBoard) + , test "decodes a False taskCompletionInLocalTime" <| + \() -> + { exampleSettingsForm | taskCompletionInLocalTime = False } + |> SD.run SettingsForm.safeDecoder + |> Result.map Settings.globalSettings + |> Result.map .taskCompletionInLocalTime + |> Expect.equal (Ok False) + , test "decodes a True taskCompletionInLocalTime" <| + \() -> + { exampleSettingsForm | taskCompletionInLocalTime = True } + |> SD.run SettingsForm.safeDecoder + |> Result.map Settings.globalSettings + |> Result.map .taskCompletionInLocalTime + |> Expect.equal (Ok True) + , test "decodes a False taskCompletionShowUtcOffset" <| + \() -> + { exampleSettingsForm | taskCompletionShowUtcOffset = False } + |> SD.run SettingsForm.safeDecoder + |> Result.map Settings.globalSettings + |> Result.map .taskCompletionShowUtcOffset + |> Expect.equal (Ok False) + , test "decodes a True taskCompletionShowUtcOffset" <| + \() -> + { exampleSettingsForm | taskCompletionShowUtcOffset = True } + |> SD.run SettingsForm.safeDecoder + |> Result.map Settings.globalSettings + |> Result.map .taskCompletionShowUtcOffset + |> Expect.equal (Ok True) , test "decodes a today string as Just the string" <| \() -> { exampleSettingsForm | today = "foo" } @@ -494,6 +524,42 @@ toggleIgnoreFileNameDate = ] +toggleTaskCompletionInLocalTime : Test +toggleTaskCompletionInLocalTime = + describe "toggleTaskCompletionInLocalTime" + [ test "toggles the value from True to False" <| + \() -> + { exampleSettingsForm | taskCompletionInLocalTime = True } + |> SettingsForm.toggleTaskCompletionInLocalTime + |> .taskCompletionInLocalTime + |> Expect.equal False + , test "toggles the value from False to False" <| + \() -> + { exampleSettingsForm | taskCompletionInLocalTime = False } + |> SettingsForm.toggleTaskCompletionInLocalTime + |> .taskCompletionInLocalTime + |> Expect.equal True + ] + + +toggleTaskCompletionShowUtcOffset : Test +toggleTaskCompletionShowUtcOffset = + describe "toggleTaskCompletionShowUtcOffset" + [ test "toggles the value from True to False" <| + \() -> + { exampleSettingsForm | taskCompletionShowUtcOffset = True } + |> SettingsForm.toggleTaskCompletionShowUtcOffset + |> .taskCompletionShowUtcOffset + |> Expect.equal False + , test "toggles the value from False to False" <| + \() -> + { exampleSettingsForm | taskCompletionShowUtcOffset = False } + |> SettingsForm.toggleTaskCompletionShowUtcOffset + |> .taskCompletionShowUtcOffset + |> Expect.equal True + ] + + updateDefaultColumnName : Test updateDefaultColumnName = describe "updateDefaultColumnName" @@ -562,10 +628,13 @@ exampleSettingsForm : SettingsForm exampleSettingsForm = { boardConfigForms = SafeZipper.empty , completed = "" + , filters = [] , future = "" , ignoreFileNameDates = False , otherTags = "" , taskCompletionFormat = "" + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False , today = "" , tomorrow = "" , undated = "" diff --git a/tests/GlobalSettingsTests.elm b/tests/GlobalSettingsTests.elm index 4f290aa1..85f87bd5 100644 --- a/tests/GlobalSettingsTests.elm +++ b/tests/GlobalSettingsTests.elm @@ -13,6 +13,7 @@ suite = concat [ default , encodeDecode + , taskCompletionSettings ] @@ -23,9 +24,12 @@ default = \() -> GlobalSettings.default |> Expect.equal - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = DefaultColumnNames.default + { defaultColumnNames = DefaultColumnNames.default + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = True + , taskCompletionShowUtcOffset = True } ] @@ -35,8 +39,7 @@ encodeDecode = describe "encoding and decoding GlobalSettings" [ test "can decode an encoded string back to the original" <| \() -> - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -45,16 +48,19 @@ encodeDecode = , untagged = Nothing , completed = Just "Done" } + , filters = [] , ignoreFileNameDates = True + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } |> TsEncode.runExample GlobalSettings.encoder |> .output - |> DecodeHelpers.runDecoder GlobalSettings.v_0_11_0_decoder + |> DecodeHelpers.runDecoder GlobalSettings.v_0_12_0_decoder |> .decoded |> Expect.equal (Ok - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -63,7 +69,32 @@ encodeDecode = , untagged = Nothing , completed = Just "Done" } + , filters = [] , ignoreFileNameDates = True + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } ) ] + + +taskCompletionSettings : Test +taskCompletionSettings = + describe "taskCompletionSettings" + [ test "returns the format, local time and utc offset settings" <| + \() -> + { defaultColumnNames = DefaultColumnNames.default + , filters = [] + , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianDataview + , taskCompletionInLocalTime = True + , taskCompletionShowUtcOffset = False + } + |> GlobalSettings.taskCompletionSettings + |> Expect.equal + { format = GlobalSettings.ObsidianDataview + , inLocalTime = True + , showUtcOffset = False + } + ] diff --git a/tests/InteropDefinitionsTests.elm b/tests/InteropDefinitionsTests.elm index 40c81641..0d533e3f 100644 --- a/tests/InteropDefinitionsTests.elm +++ b/tests/InteropDefinitionsTests.elm @@ -35,7 +35,88 @@ suite = flagsTests : Test flagsTests = describe "interop.flags (decoding)" - [ test "decodes valid flags for settings version 0.11.0" <| + [ test "decodes valid flags for settings version 0.12.0" <| + \() -> + """{"now":11,"zone":22,"uniqueId":"12345","rightToLeft":false,"dataviewTaskCompletion":{"taskCompletionTracking":true,"taskCompletionUseEmojiShorthand":false,"taskCompletionText":"completion"},"settings":{"version":"0.12.0","data":{"globalSettings":{"defaultColumnNames":{"today":"Do Today","tomorrow":"","future":"The Future","undated":"","otherTags":"The Others","untagged":"","completed":"Completed"},"filters":[{"tag":"pathFilter","data":"b/path"},{"tag":"fileFilter","data":"aFile"}],"ignoreFileNameDates":true,"taskCompletionFormat":"ObsidianTasks","taskCompletionInLocalTime":true,"taskCompletionShowUtcOffset":false}, + "boardConfigs":[ + {"filters":[{"tag":"pathFilter","data":"a/path"},{"tag":"tagFilter","data":"tag1"}], + "filterPolarity":"Deny", + "filterScope":"TopLevelOnly", + "showFilteredTags":true, + "showColumnTags":false, + "columns":[{"tag":"undated","data":{"collapsed":false,"name":"Undated"}},{"tag":"dated","data":{"collapsed":false,"name":"Do Today","range":{"tag":"before","data":1}}},{"tag":"dated","data":{"collapsed":false,"name":"Tomorrow","range":{"tag":"between","data":{"from":1,"to":1}}}},{"tag":"dated","data":{"collapsed":false,"name":"The Future","range":{"tag":"after","data":1}}},{"tag":"completed","data":{"collapsed":false,"name":"Completed","index":4,"limit":4}}], + "name":"date board name"}, + {"columns":[{"tag":"untagged","data":{"collapsed":false,"name":"Untagged"}},{"tag":"namedTag","data":{"collapsed":true,"name":"name 1","tag":"tag1"}},{"tag":"completed","data":{"collapsed":false,"name":"Completed","index":2,"limit":5}}], + "showColumnTags":false, + "filters":[{"tag":"pathFilter","data":"b/path"},{"tag":"tagFilter","data":"tag2"}], + "filterPolarity":"Allow", + "filterScope":"SubTasksOnly", + "showFilteredTags":false, + "name":"tag board name"}]}}}""" + |> DecodeHelpers.runDecoder interop.flags + |> .decoded + |> Expect.equal + (Ok + { settings = + { version = Semver.version 0 12 0 [] [] + , boardConfigs = + SafeZipper.fromList + [ BoardConfig + { columns = + Columns.fromList + [ Column.undated "Undated" + , Column.dated (DatedColumn.init "Do Today" <| DatedColumn.Before 1) + , Column.dated (DatedColumn.init "Tomorrow" <| DatedColumn.Between { from = 1, to = 1 }) + , Column.dated (DatedColumn.init "The Future" <| DatedColumn.After 1) + , Column.completed (CompletedColumn.init "Completed" 4 4) + ] + , filters = [ FilterHelpers.pathFilter "a/path", FilterHelpers.tagFilter "tag1" ] + , filterPolarity = Filter.Deny + , filterScope = Filter.TopLevelOnly + , showColumnTags = False + , showFilteredTags = True + , name = "date board name" + } + , BoardConfig + { columns = + Columns.fromList + [ Column.untagged "Untagged" + , Column.namedTag "name 1" "tag1" |> Column.setCollapse True + , Column.completed (CompletedColumn.init "Completed" 2 5) + ] + , filters = [ FilterHelpers.pathFilter "b/path", FilterHelpers.tagFilter "tag2" ] + , filterPolarity = Filter.Allow + , filterScope = Filter.SubTasksOnly + , showColumnTags = False + , showFilteredTags = False + , name = "tag board name" + } + ] + , globalSettings = + { defaultColumnNames = + { today = Just "Do Today" + , tomorrow = Nothing + , future = Just "The Future" + , undated = Nothing + , otherTags = Just "The Others" + , untagged = Nothing + , completed = Just "Completed" + } + , filters = [ FilterHelpers.pathFilter "b/path", FilterHelpers.fileFilter "aFile" ] + , ignoreFileNameDates = True + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = True + , taskCompletionShowUtcOffset = False + } + } + , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" + , rightToLeft = False + , now = 11 + , zone = 22 + , uniqueId = "12345" + } + ) + , test "decodes valid flags for settings version 0.11.0" <| \() -> """{"now":11,"zone":22,"uniqueId":"12345","rightToLeft":false,"dataviewTaskCompletion":{"taskCompletionTracking":true,"taskCompletionUseEmojiShorthand":false,"taskCompletionText":"completion"},"settings":{"version":"0.11.0","data":{"globalSettings":{"taskCompletionFormat":"ObsidianTasks","defaultColumnNames":{"today":"Do Today","tomorrow":"","future":"The Future","undated":"","otherTags":"The Others","untagged":"","completed":"Completed"},"ignoreFileNameDates":true}, "boardConfigs":[ @@ -58,7 +139,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -93,8 +174,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -103,7 +183,11 @@ flagsTests = , untagged = Nothing , completed = Just "Completed" } + , filters = [] , ignoreFileNameDates = True + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -121,7 +205,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -156,8 +240,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -166,7 +249,11 @@ flagsTests = , untagged = Nothing , completed = Just "Completed" } + , filters = [] , ignoreFileNameDates = True + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -184,7 +271,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -219,8 +306,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -229,7 +315,11 @@ flagsTests = , untagged = Nothing , completed = Just "Completed" } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -247,7 +337,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -282,8 +372,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -292,7 +381,11 @@ flagsTests = , untagged = Nothing , completed = Just "Completed" } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -310,7 +403,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -345,8 +438,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Just "Do Today" , tomorrow = Nothing , future = Just "The Future" @@ -355,7 +447,11 @@ flagsTests = , untagged = Nothing , completed = Just "Completed" } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -373,7 +469,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -408,8 +504,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -418,7 +513,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -436,7 +535,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -471,8 +570,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianTasks - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -481,7 +579,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianTasks + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -499,7 +601,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -534,8 +636,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -544,7 +645,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -562,7 +667,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -597,8 +702,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -607,7 +711,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -625,7 +733,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -660,8 +768,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -670,7 +777,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -688,7 +799,7 @@ flagsTests = |> Expect.equal (Ok { settings = - { version = Semver.version 0 11 0 [] [] + { version = Semver.version 0 12 0 [] [] , boardConfigs = SafeZipper.fromList [ BoardConfig @@ -723,8 +834,7 @@ flagsTests = } ] , globalSettings = - { taskCompletionFormat = GlobalSettings.ObsidianCardBoard - , defaultColumnNames = + { defaultColumnNames = { today = Nothing , tomorrow = Nothing , future = Nothing @@ -733,7 +843,11 @@ flagsTests = , untagged = Nothing , completed = Nothing } + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.ObsidianCardBoard + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } } , dataviewTaskCompletion = DataviewTaskCompletion.Text "completion" @@ -919,49 +1033,49 @@ toElmTests = """{"tag":"settingsUpdated","data":{"version":"0.8.0","data":{"boardConfigs":[],"globalSettings":{"taskCompletionFormat":"ObsidianDataview","columnNames":{"today":"","tomorrow":"","future":"","undated":"","others":"","untagged":"","completed":""}}}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { taskCompletionFormat = GlobalSettings.ObsidianDataview, defaultColumnNames = DefaultColumnNames.default, ignoreFileNameDates = False } }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianDataview, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.7.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.7.0","data":{"boardConfigs":[],"globalSettings":{"taskCompletionFormat":"ObsidianDataview","columnNames":{"today":"","tomorrow":"","future":"","undated":"","others":"","untagged":"","completed":""}}}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { taskCompletionFormat = GlobalSettings.ObsidianDataview, defaultColumnNames = DefaultColumnNames.default, ignoreFileNameDates = False } }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianDataview, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.6.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.6.0","data":{"boardConfigs":[],"globalSettings":{"taskCompletionFormat":"ObsidianDataview"}}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { taskCompletionFormat = GlobalSettings.ObsidianDataview, defaultColumnNames = DefaultColumnNames.default, ignoreFileNameDates = False } }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianDataview, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.5.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.5.0","data":{"boardConfigs":[],"globalSettings":{"taskUpdateFormat":"ObsidianCardBoard"}}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = GlobalSettings.default }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianCardBoard, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.4.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.4.0","data":{"boardConfigs":[]}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = GlobalSettings.default }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianCardBoard, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.3.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.3.0","data":{"boardConfigs":[]}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = GlobalSettings.default }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianCardBoard, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.2.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.2.0","data":{"boardConfigs":[],"globalSettings":{"hideCompletedSubtasks":false,"ignorePaths":[],"subTaskDisplayLimit":null}}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = GlobalSettings.default }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianCardBoard, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "decodes version 0.1.0 settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"0.1.0","data":{"boardConfigs":[]}}}""" |> DecodeHelpers.runDecoder interop.toElm |> .decoded - |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 11 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = GlobalSettings.default }) + |> Expect.equal (Ok <| InteropDefinitions.SettingsUpdated { version = Semver.version 0 12 0 [] [], boardConfigs = SafeZipper.fromList [], globalSettings = { defaultColumnNames = DefaultColumnNames.default, filters = [], ignoreFileNameDates = False, taskCompletionFormat = GlobalSettings.ObsidianCardBoard, taskCompletionInLocalTime = False, taskCompletionShowUtcOffset = False } }) , test "fails to decode an unsupported version of settings data" <| \() -> """{"tag":"settingsUpdated","data":{"version":"99999.0.0","data":{"boardConfigs":[]}}}""" diff --git a/tests/MarkdownFileTests.elm b/tests/MarkdownFileTests.elm index 8c8727f0..6ab83904 100644 --- a/tests/MarkdownFileTests.elm +++ b/tests/MarkdownFileTests.elm @@ -52,6 +52,13 @@ decoderTests = |> .decoded |> Result.map .frontMatterTags |> Expect.equal (Ok <| TagList.fromList [ "tag1", "tag2" ]) + , test "extracts (inline) tags with no brackets from the front matter block" <| + \() -> + "{\"filePath\":\"a path\",\"fileDate\":\"a date\",\"fileContents\":\"---\\ntags: tag1, tag2\\n---\\nsome contents\"}" + |> DecodeHelpers.runDecoder decoder + |> .decoded + |> Result.map .frontMatterTags + |> Expect.equal (Ok <| TagList.fromList [ "tag1", "tag2" ]) , test "extracts (top level) tags from the front matter block" <| \() -> "{\"filePath\":\"a path\",\"fileDate\":\"a date\",\"fileContents\":\"---\\ntags:\\n- tag1\\n- tag2\\n---\\nsome contents\"}" diff --git a/tests/ParserHelperTests.elm b/tests/ParserHelperTests.elm index c0d5f77c..294422bb 100644 --- a/tests/ParserHelperTests.elm +++ b/tests/ParserHelperTests.elm @@ -305,6 +305,16 @@ timeParserTests = "2020-01-02T01:30:23" |> P.run timeParser |> Expect.equal (Ok <| Time.millisToPosix 1577928623000) + , test "parses valid time string with hh:mm:ssZ included" <| + \() -> + "2020-01-02T01:30:23Z" + |> P.run timeParser + |> Expect.equal (Ok <| Time.millisToPosix 1577928623000) + , test "parses valid time string with hh:mm:ss+05:30 included" <| + \() -> + "2020-01-02T01:30:23+05:30" + |> P.run timeParser + |> Expect.equal (Ok <| Time.millisToPosix 1577908823000) , test "fails with an invalid time string" <| \() -> "2020-41-02" diff --git a/tests/SettingsTests.elm b/tests/SettingsTests.elm index 68c7ba45..14b9739a 100644 --- a/tests/SettingsTests.elm +++ b/tests/SettingsTests.elm @@ -89,11 +89,11 @@ cleanupNames = currentVersion : Test currentVersion = describe "currentVersion" - [ test "is 0.11.0" <| + [ test "is 0.12.0" <| \() -> Settings.currentVersion |> Semver.print - |> Expect.equal "0.11.0" + |> Expect.equal "0.12.0" ] @@ -325,9 +325,12 @@ uniqueBoardNames = exampleGlobalSettings : GlobalSettings exampleGlobalSettings = - { taskCompletionFormat = GlobalSettings.NoCompletion - , defaultColumnNames = DefaultColumnNames.default + { defaultColumnNames = DefaultColumnNames.default + , filters = [] , ignoreFileNameDates = False + , taskCompletionFormat = GlobalSettings.NoCompletion + , taskCompletionInLocalTime = False + , taskCompletionShowUtcOffset = False } diff --git a/tests/TagListTests.elm b/tests/TagListTests.elm index 2fda8882..3cc5e397 100644 --- a/tests/TagListTests.elm +++ b/tests/TagListTests.elm @@ -20,7 +20,7 @@ suite = , fromList , isEmpty , sort - , toList + , toStrings , unique ] @@ -270,18 +270,18 @@ sort = \() -> TagList.fromList [ "foo", "bar" ] |> TagList.sort - |> TagList.toList + |> TagList.toStrings |> Expect.equal [ "bar", "foo" ] ] -toList : Test -toList = - describe "toList" +toStrings : Test +toStrings = + describe "toStrings" [ test "returns the TagList as a list of Strings" <| \() -> TagList.fromList [ "foo", "bar" ] - |> TagList.toList + |> TagList.toStrings |> Expect.equal [ "foo", "bar" ] ] diff --git a/tests/TagTests.elm b/tests/TagTests.elm index 8db4644a..15a94508 100644 --- a/tests/TagTests.elm +++ b/tests/TagTests.elm @@ -14,6 +14,7 @@ suite = concat [ containsInvalidCharacters , equals + , matches , parser , startsWith , toString @@ -64,6 +65,84 @@ equals = ] +matches : Test +matches = + describe "matches" + [ describe "basic match string (no subtags)" + [ test "returns True if the tag matches" <| + \() -> + "#foo" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo") + |> Expect.equal (Ok True) + , test "matches are case insensative" <| + \() -> + "#foo" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "fOO") + |> Expect.equal (Ok True) + , test "returns False if there is no match" <| + \() -> + "#foo" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "xxx") + |> Expect.equal (Ok False) + , test "returns False if the tag starts with the match string" <| + \() -> + "#foo" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "fo") + |> Expect.equal (Ok False) + , test "returns False if the tag has a '/' on the end" <| + \() -> + "#foo/" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo") + |> Expect.equal (Ok False) + , test "returns False if the tag is a subtag of the match string" <| + \() -> + "#foo/bar" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo") + |> Expect.equal (Ok False) + ] + , describe "match string with subtags" + [ test "returns True if the tag matches" <| + \() -> + "#foo/bar" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo/bar") + |> Expect.equal (Ok True) + , test "returns False if the tag has a '/' on the end" <| + \() -> + "#foo/bar/" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo/bar") + |> Expect.equal (Ok False) + ] + , describe "match string with subtag wildcards" + [ test "returns True if the tag matches exactly" <| + \() -> + "#foo/bar/" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo/bar/") + |> Expect.equal (Ok True) + , test "returns True if the tag is a subtag of the match string" <| + \() -> + "#foo/bar/baz" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo/bar/") + |> Expect.equal (Ok True) + , test "returns True if the tag is the root of the match string" <| + \() -> + "#foo/bar" + |> Parser.run Tag.parser + |> Result.map (Tag.matches "foo/bar/") + |> Expect.equal (Ok True) + ] + ] + + parser : Test parser = describe "parser" diff --git a/tests/TaskItemTests.elm b/tests/TaskItemTests.elm index 031bf4c6..56809914 100644 --- a/tests/TaskItemTests.elm +++ b/tests/TaskItemTests.elm @@ -3,7 +3,9 @@ module TaskItemTests exposing (suite) import DataviewTaskCompletion import Date import Expect +import Filter import GlobalSettings +import Helpers.FilterHelpers as FilterHelpers import Helpers.TaskHelpers as TaskHelpers import Helpers.TaskItemHelpers as TaskItemHelpers import Maybe.Extra as ME @@ -22,20 +24,16 @@ suite = , completedPosix , completion , containsId - , descendantTaskHasThisTag , descendantTasks , due , filePath - , hasAnyIncompleteSubtasksWithTagsOtherThanThese - , hasIncompleteTaskWithThisTag - , hasOneOfTheTags , hasTags - , hasTaskWithTagOtherThanThese , hasThisTagBasic , hasThisTagWithSubtag , hasThisTagWithSubtagWildcard , hasTopLevelTags , id + , isAllowed , isCompleted , isFromFile , isDated @@ -43,13 +41,13 @@ suite = , notes , originalText , parsing + , removeMatchingTags , removeTags , tags , tasksToToggle , title , titleWithTags , topLevelTags - , topLevelTaskHasThisTag , toToggledString , updateFilePath ] @@ -319,36 +317,6 @@ containsId = ] -descendantTaskHasThisTag : Test -descendantTaskHasThisTag = - describe "descendantTaskHasThisTag" - [ test "returns False for (theTag) '- [ ] foo" <| - \() -> - "- [ ] foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.descendantTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - , test "returns False for (theTag) '- [ ] foo #theTag'" <| - \() -> - "- [ ] foo #theTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.descendantTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - , test "returns False for (theTag) '- [ ] foo\n - [ ] bar #otherTag'" <| - \() -> - "- [ ] foo\n - [ ] bar #otherTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.descendantTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - , test "returns True for (theTag) '- [ ] foo\n - [ ] bar #thisTag'" <| - \() -> - "- [ ] foo\n - [ ] bar #theTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.descendantTaskHasThisTag "theTag") - |> Expect.equal (Ok True) - ] - - descendantTasks : Test descendantTasks = describe "descendantTasks" @@ -366,6 +334,13 @@ descendantTasks = |> Result.map TaskItem.descendantTasks |> Result.map (List.map TaskItem.title) |> Expect.equal (Ok [ "bar" ]) + , test "parses multiple descendantTasks including grandkids" <| + \() -> + "- [ ] foo\n - [ ] bar\n - [ ] baz\n - [ ] qaz" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map TaskItem.descendantTasks + |> Result.map (List.map TaskItem.title) + |> Expect.equal (Ok [ "bar", "baz", "qaz" ]) , test "stops parsing descendantTasks at the end of indentation" <| \() -> "- [ ] foo\n - [ ] bar\n - [ ] baz\n- [ ] roo" @@ -532,166 +507,6 @@ filePath = ] -hasAnyIncompleteSubtasksWithTagsOtherThanThese : Test -hasAnyIncompleteSubtasksWithTagsOtherThanThese = - describe "hasAnyIncompleteSubtasksWithTagsOtherThanThese" - [ describe "incomplete task" - [ test "returns False for a task with no sub-tasks that has another tag" <| - \() -> - "- [ ] foo #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task with an incomplete sub-task with no tag" <| - \() -> - "- [ ] foo #atag\n - [ ] bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task with an incomplete sub-task with one of the given tags" <| - \() -> - "- [ ] foo #atag\n - [ ] bar #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns True for a task with an incomplete sub-task with a different tag" <| - \() -> - "- [ ] foo #atag\n - [ ] bar #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True for a task with an incomplete sub-task with a different tag and another that matches" <| - \() -> - "- [ ] foo #atag\n - [ ] bar #atag - [ ] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True for a task with an incomplete sub-task with a different tag and another that is complete and matches" <| - \() -> - "- [ ] foo #atag\n - [ ] bar #atag - [x] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns False for a task with a completed sub-task with a different tag and another that is not complete and matches" <| - \() -> - "- [ ] foo #atag\n - [x] bar #atag - [ ] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - ] - , describe "completed task" - [ test "returns False for a task with no sub-tasks that has another tag" <| - \() -> - "- [x] foo #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task with an incomplete sub-task with no tag" <| - \() -> - "- [x] foo #atag\n - [ ] bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task with an incomplete sub-task with one of the given tags" <| - \() -> - "- [x] foo #atag\n - [ ] bar #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - , test "returns True for a task with an incomplete sub-task with a different tag" <| - \() -> - "- [x] foo #atag\n - [ ] bar #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True for a task with an incomplete sub-task with a different tag and another that matches" <| - \() -> - "- [x] foo #atag\n - [ ] bar #atag - [ ] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True for a task with an incomplete sub-task with a different tag and another that is complete and matches" <| - \() -> - "- [x] foo #atag\n - [ ] bar #atag - [x] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok True) - , test "returns False for a task with a completed sub-task with a different tag and another that is not complete and matches" <| - \() -> - "- [x] foo #atag\n - [x] bar #atag - [ ] baz #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasAnyIncompleteSubtasksWithTagsOtherThanThese [ "ztag" ]) - |> Expect.equal (Ok False) - ] - ] - - -hasIncompleteTaskWithThisTag : Test -hasIncompleteTaskWithThisTag = - describe "hasIncompleteTaskWithTag - basic operation" - [ test "returns True for a task with no sub-tasks that has the tag" <| - \() -> - "- [ ] foo #bar #foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok True) - , test "returns True for a task without the tag with no sub-tasks, but the tag is in the front matter" <| - \() -> - "- [ ] foo" - |> Parser.run (TaskItem.parser DataviewTaskCompletion.NoCompletion "" Nothing (TagList.fromList [ "bar" ]) 0) - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok True) - , test "returns True for a task with no matching tag but a sub-tasks has the tag" <| - \() -> - "- [ ] foo #foo\n - [ ] bar #bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok True) - , test "returns False for a task with no sub-tasks that doesn't have the tag" <| - \() -> - "- [ ] foo #bar #foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "baz") - |> Expect.equal (Ok False) - , test "returns False for a task with no sub-tasks that has the tag but is completed" <| - \() -> - "- [x] foo #bar #foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok False) - , test "returns False for a completed task with no sub-tasks without the tag, but the tag is in the front matter" <| - \() -> - "- [x] foo" - |> Parser.run (TaskItem.parser DataviewTaskCompletion.NoCompletion "" Nothing (TagList.fromList [ "bar" ]) 0) - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok False) - , test "returns False for a task with no matching tag plus a sub-tasks has the tag but is completed" <| - \() -> - "- [ ] foo #foo\n - [x] bar #bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasIncompleteTaskWithThisTag "bar") - |> Expect.equal (Ok False) - ] - - -hasOneOfTheTags : Test -hasOneOfTheTags = - describe "hasOneOfTheTags - basic operation" - [ test "returns True if the task has one of the tags" <| - \() -> - "- [ ] foo #bar #foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasOneOfTheTags [ "bar", "baz" ]) - |> Expect.equal (Ok True) - , test "returns False if the task has none of the tags" <| - \() -> - "- [ ] foo #bar #foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasOneOfTheTags [ "qux", "baz" ]) - |> Expect.equal (Ok False) - ] - - hasTags : Test hasTags = describe "hasTags" @@ -722,82 +537,6 @@ hasTags = ] -hasTaskWithTagOtherThanThese : Test -hasTaskWithTagOtherThanThese = - describe "hasTaskWithTagOtherThanThese" - [ describe "with no sub-tasks" - [ test "returns True for a task which has a tag, but none of those given" <| - \() -> - "- [ ] foo #aTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True for a task which has a tag, in addition to those given" <| - \() -> - "- [ ] foo #aTag #yTag #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok True) - , test "returns False for a task which has no tags when none are given either" <| - \() -> - "- [ ] foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese []) - |> Expect.equal (Ok False) - , test "returns False for a task which has no tags" <| - \() -> - "- [ ] foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task which has no tags other than one of those given" <| - \() -> - "- [ ] foo #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False for a task which has exaclty the same as the given tags" <| - \() -> - "- [ ] foo #ytag #ztag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok False) - ] - , describe "with sub-tasks" - [ test "returns False where the task and sub-tasks have no tags" <| - \() -> - "- [ ] foo\n - [ ] bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok False) - , test "returns False where the task and sub-tasks have no tags and none are given" <| - \() -> - "- [ ] foo\n - [ ] bar" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese []) - |> Expect.equal (Ok False) - , test "returns True where the sub-task has a tag other than those given" <| - \() -> - "- [ ] foo\n - [ ] bar #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok True) - , test "returns True where the sub-task has a tag other than those given even if the main task has a matching tag" <| - \() -> - "- [ ] foo #ztag\n - [ ] bar #atag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok True) - , test "returns False where the sub- and main task have matching tags" <| - \() -> - "- [ ] foo #ztag\n - [ ] bar #ytag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.hasTaskWithTagOtherThanThese [ "ytag", "ztag" ]) - |> Expect.equal (Ok False) - ] - ] - - hasThisTagBasic : Test hasThisTagBasic = describe "hasThisTag - basic operation" @@ -966,6 +705,137 @@ id = ] +isAllowed : Test +isAllowed = + describe "isAllowed" + [ test "returns True for a matching file filter" <| + \() -> + FilterHelpers.fileFilter "a/b/c.ext" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "a/b/c.ext") + |> Expect.equal True + , test "returns False for a non-matching file filter" <| + \() -> + FilterHelpers.fileFilter "a/b/c.diff" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "a/b/c.ext") + |> Expect.equal False + , test "returns True for a matching windows path filter for the full path" <| + \() -> + FilterHelpers.pathFilter "aa\\\\bb" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal True + , test "returns True for a matching windows path filter with a trailing \\" <| + \() -> + FilterHelpers.pathFilter "aa\\\\bb\\\\" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal True + , test "returns True for a matching windows path filter for the first part of the path" <| + \() -> + FilterHelpers.pathFilter "aa" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal True + , test "returns True for a matching windows path filter of \\" <| + \() -> + FilterHelpers.pathFilter "\\\\" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal True + , test "returns True for an empty windows path filter" <| + \() -> + FilterHelpers.pathFilter "" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal True + , test "returns False if the windows path filter only contains a part of the last path componant" <| + \() -> + FilterHelpers.pathFilter "aa\\\\b" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal False + , test "returns False if the windows path filter contains the file name" <| + \() -> + FilterHelpers.pathFilter "aa\\\\bb\\\\c" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal False + , test "returns False if the windows path filter contains the file name & extension" <| + \() -> + FilterHelpers.pathFilter "aa\\\\bb\\\\c.ext" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa\\bb\\c.ext") + |> Expect.equal False + , test "returns True for a matching path filter for the full path" <| + \() -> + FilterHelpers.pathFilter "aa/bb" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal True + , test "returns True for a matching path filter with a trailing /" <| + \() -> + FilterHelpers.pathFilter "aa/bb/" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal True + , test "returns True for a matching path filter for the first part of the path" <| + \() -> + FilterHelpers.pathFilter "aa" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal True + , test "returns True for a matching path filter of /" <| + \() -> + FilterHelpers.pathFilter "/" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal True + , test "returns True for an empty path filter" <| + \() -> + FilterHelpers.pathFilter "" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal True + , test "returns False if the path filter only contains a part of the last path componant" <| + \() -> + FilterHelpers.pathFilter "aa/b" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal False + , test "returns False if the path filter contains the file name" <| + \() -> + FilterHelpers.pathFilter "aa/bb/c" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal False + , test "returns False if the path filter contains the file name & extension" <| + \() -> + FilterHelpers.pathFilter "aa/bb/c.ext" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo" "aa/bb/c.ext") + |> Expect.equal False + , test "returns True for a matching top level tag when the scope is Both" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") + |> Expect.equal True + , test "returns True for a matching top level tag when the scope is TopLevelOnly" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.TopLevelOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") + |> Expect.equal True + , test "returns False for a matching top level tag when the scope is SubTasksOnly" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.SubTasksOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo #taga #tagb" "") + |> Expect.equal False + , test "returns True for a matching sub task tag when the scope is Both" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") + |> Expect.equal True + , test "returns False for a matching sub task tag when the scope is TopLevelOnly" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.TopLevelOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") + |> Expect.equal False + , test "returns True for a matching sub task tag when the scope is SubTasksOnly" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.SubTasksOnly (TaskItemHelpers.exampleTaskItem "- [ ] foo\n - [ ] bar #taga #tagb" "") + |> Expect.equal True + , test "returns False for a non-matching tag filter" <| + \() -> + FilterHelpers.tagFilter "taga" + |> TaskItem.isAllowed Filter.Both (TaskItemHelpers.exampleTaskItem "- [ ] foo #tagb tagc" "") + |> Expect.equal False + ] + + isCompleted : Test isCompleted = describe "isCompleted" @@ -1199,6 +1069,48 @@ parsing = ] +removeMatchingTags : Test +removeMatchingTags = + describe "removeMatchingTags" + [ test "removes an exact match from a TaskItem" <| + \() -> + "- [ ] foo #foo #bar" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map (TaskItem.removeMatchingTags "foo") + |> Result.map TaskItem.tags + |> Result.map TagList.toStrings + |> Result.map List.sort + |> Expect.equal (Ok [ "bar" ]) + , test "removes tags that match a subtag wildcard" <| + \() -> + "- [ ] foo #foo/bar #bar #foo/ #foo #foo/poo" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map (TaskItem.removeMatchingTags "foo/") + |> Result.map TaskItem.tags + |> Result.map TagList.toStrings + |> Result.map List.sort + |> Expect.equal (Ok [ "bar" ]) + , test "removes tags that match a subtag" <| + \() -> + "- [ ] foo #foo #bar #foo/bar #foo/" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map (TaskItem.removeMatchingTags "foo/bar") + |> Result.map TaskItem.tags + |> Result.map TagList.toStrings + |> Result.map List.sort + |> Expect.equal (Ok [ "bar", "foo", "foo/" ]) + , test "does not affect subtasks" <| + \() -> + "- [ ] foo #bar\n - [ ] bar #foo #baz" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map (TaskItem.removeMatchingTags "foo") + |> Result.map TaskItem.tags + |> Result.map TagList.toStrings + |> Result.map List.sort + |> Expect.equal (Ok [ "bar", "baz", "foo" ]) + ] + + removeTags : Test removeTags = describe "removeTags" @@ -1208,7 +1120,7 @@ removeTags = |> Parser.run TaskItemHelpers.basicParser |> Result.map (TaskItem.removeTags [ "foo", "baz" ]) |> Result.map TaskItem.tags - |> Result.map TagList.toList + |> Result.map TagList.toStrings |> Result.map List.sort |> Expect.equal (Ok [ "bar", "baza", "foo/", "qux" ]) , test "removes from a TaskItem and it's subtasks" <| @@ -1217,7 +1129,7 @@ removeTags = |> Parser.run TaskItemHelpers.basicParser |> Result.map (TaskItem.removeTags [ "foo", "baz" ]) |> Result.map TaskItem.tags - |> Result.map TagList.toList + |> Result.map TagList.toStrings |> Result.map List.sort |> Expect.equal (Ok [ "bar", "baza", "foo/", "qux" ]) ] @@ -1399,36 +1311,6 @@ topLevelTags = ] -topLevelTaskHasThisTag : Test -topLevelTaskHasThisTag = - describe "topLevelTaskHasThisTag" - [ test "returns False for (theTag) '- [ ] foo" <| - \() -> - "- [ ] foo" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.topLevelTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - , test "returns True for (theTag) '- [ ] foo #theTag'" <| - \() -> - "- [ ] foo #theTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.topLevelTaskHasThisTag "theTag") - |> Expect.equal (Ok True) - , test "returns False for (theTag) '- [ ] foo #otherTag \n - [ ] bar #otherTag'" <| - \() -> - "- [ ] foo #otherTag\n - [ ] bar #otherTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.topLevelTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - , test "returns False for (theTag) '- [ ] foo\n - [ ] bar #thisTag'" <| - \() -> - "- [ ] foo\n - [ ] bar #theTag" - |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.topLevelTaskHasThisTag "theTag") - |> Expect.equal (Ok False) - ] - - toToggledString : Test toToggledString = describe "toToggledString" @@ -1436,55 +1318,141 @@ toToggledString = \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.NoCompletion { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.NoCompletion + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 ^12345") - , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianCardBoard format" <| + , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianCardBoard format (local = False, offset = False)" <| \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.ObsidianCardBoard { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 @completed(1970-01-01T00:00:00) ^12345") + , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianCardBoard format (local = True, offset = True)" <| + \() -> + "- [ ] foo #tag1 bar #tag2 ^12345" + |> Parser.run TaskItemHelpers.basicParser + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = True + , showUtcOffset = True + } + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + ) + |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 @completed(1970-01-01T05:00:00+05:00) ^12345") , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianTasks format" <| \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.ObsidianTasks { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianTasks + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 ✅ 1970-01-01 ^12345") , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianDataview custom format" <| \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString (DataviewTaskCompletion.Text "done") GlobalSettings.ObsidianDataview { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + (DataviewTaskCompletion.Text "done") + { format = GlobalSettings.ObsidianDataview + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 [done:: 1970-01-01] ^12345") , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianDataview emoji format" <| \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.Emoji GlobalSettings.ObsidianDataview { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.Emoji + { format = GlobalSettings.ObsidianDataview + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 ✅ 1970-01-01 ^12345") , test "given an INCOMPLETE item it outputs a string for a completed task in ObsidianDataview no completion" <| \() -> "- [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.ObsidianDataview { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianDataview + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [x] foo #tag1 bar #tag2 ^12345") , test "given an item with an 'x' in the checkbox outputs a string for an incomplete task removing all formats of completed marks" <| \() -> - "- [x] foo #tag1 bar #tag2 @completed(2020-03-22T00:00:00) ✅ 1970-01-01 [done:: 2021-01-01] ^12345" + "- [x] foo #tag1 bar #tag2 @completed(2020-03-22T00:00:00Z) @completed(2020-03-22T00:00:00-01:00) @completed(2020-03-22T00:00:00+01:00) @completed(2020-03-22T00:00:00) ✅ 1970-01-01 [done:: 2021-01-01] ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString (DataviewTaskCompletion.Text "done") GlobalSettings.ObsidianCardBoard { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + (DataviewTaskCompletion.Text "done") + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [ ] foo #tag1 bar #tag2 ^12345") , test "doesn't remove dataview format if it has been set to NoCompletion" <| \() -> "- [x] foo #tag1 bar #tag2 @completed(2020-03-22T00:00:00) ✅ 1970-01-01 [done:: 2021-01-01] ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.ObsidianCardBoard { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [ ] foo #tag1 bar #tag2 [done:: 2021-01-01] ^12345") , test "given an item with an 'X' in the checkbox outputs a string for an incomplete task removing all formats of completed marks" <| \() -> - "- [X] [custom:: 2021-01-01] foo #tag1 ✅ 1970-01-01 @completed(2020-03-22T00:00:00) bar #tag2" + "- [X] [custom:: 2021-01-01] foo #tag1 @completed(2020-03-22T00:00:00Z) @completed(2020-03-22T00:00:00-01:00) @completed(2020-03-22T00:00:00+01:00) @completed(2020-03-22T00:00:00) ✅ 1970-01-01 bar #tag2" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString (DataviewTaskCompletion.Text "custom") GlobalSettings.ObsidianCardBoard { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + (DataviewTaskCompletion.Text "custom") + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "- [ ] foo #tag1 bar #tag2") , test "preserves leading whitespace for descendant tasks" <| \() -> @@ -1492,7 +1460,15 @@ toToggledString = |> Parser.run TaskItemHelpers.basicParser |> Result.map TaskItem.descendantTasks |> Result.withDefault [] - |> List.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.ObsidianCardBoard { time = Time.millisToPosix 0 }) + |> List.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal [ " \t- [x] a subtask @completed(1970-01-01T00:00:00)" ] , test "preserves leading whitepace" <| \() -> @@ -1502,13 +1478,29 @@ toToggledString = |> Maybe.map TaskItem.descendantTasks |> Maybe.map List.head |> ME.join - |> Maybe.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.NoCompletion { time = Time.millisToPosix 0 }) + |> Maybe.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.NoCompletion + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Just " - [x] bar #tag1 bar #tag2 ^12345") , test "preserves a '+' list marker" <| \() -> "+ [ ] foo #tag1 bar #tag2 ^12345" |> Parser.run TaskItemHelpers.basicParser - |> Result.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.NoCompletion { time = Time.millisToPosix 0 }) + |> Result.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.NoCompletion + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Ok "+ [x] foo #tag1 bar #tag2 ^12345") , test "preserves leading whitepace with a '*' list marker" <| \() -> @@ -1518,7 +1510,15 @@ toToggledString = |> Maybe.map TaskItem.descendantTasks |> Maybe.map List.head |> ME.join - |> Maybe.map (TaskItem.toToggledString DataviewTaskCompletion.NoCompletion GlobalSettings.NoCompletion { time = Time.millisToPosix 0 }) + |> Maybe.map + (TaskItem.toToggledString + DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.NoCompletion + , inLocalTime = False + , showUtcOffset = False + } + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + ) |> Expect.equal (Just " * [x] bar #tag1 bar #tag2 ^12345") ] diff --git a/tests/TaskListTests.elm b/tests/TaskListTests.elm index adb1cb82..6134815e 100644 --- a/tests/TaskListTests.elm +++ b/tests/TaskListTests.elm @@ -5,7 +5,6 @@ import Expect import Helpers.TaskHelpers as TaskHelpers import Helpers.TaskItemHelpers as TaskItemHelpers import Helpers.TaskListHelpers as TaskListHelpers -import List.Extra as LE import Parser import TagList import TaskItem exposing (TaskItem) @@ -21,7 +20,6 @@ suite = , filter , map , parsing - , removeTags , replaceForFile , removeForFile , taskContainingId @@ -253,21 +251,6 @@ not a task ] -removeTags : Test -removeTags = - describe "removeTags" - [ test "removes tags from all TaskItems in the list that exaactly match the given strings" <| - \() -> - TaskListHelpers.exampleTagBoardTaskList - |> TaskList.removeTags [ "tag1", "tag2" ] - |> TaskList.tasks - |> List.map TaskItem.tags - |> List.concatMap TagList.toList - |> LE.unique - |> Expect.equal [ "tag3", "tag4" ] - ] - - replaceForFile : Test replaceForFile = describe "replacing tasks from a chosen file" diff --git a/tests/TimeWithZoneTests.elm b/tests/TimeWithZoneTests.elm new file mode 100644 index 00000000..fc8cd99c --- /dev/null +++ b/tests/TimeWithZoneTests.elm @@ -0,0 +1,200 @@ +module TimeWithZoneTests exposing (suite) + +import DataviewTaskCompletion +import Expect +import Fuzz +import GlobalSettings +import Test exposing (..) +import Time +import TimeWithZone + + +suite : Test +suite = + concat + [ completionString + , toString + ] + + +startOf2024 : Int +startOf2024 = + 1704067200000 + + +completionString : Test +completionString = + describe "completionString" + [ fuzz3 (Fuzz.intRange -1440 1440) Fuzz.bool Fuzz.bool "returns an empty string if the format is NoCompletion" <| + \zone inLocalTime showUtcOffset -> + { time = Time.millisToPosix 0, zone = Time.customZone zone [] } + |> TimeWithZone.completionString DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.NoCompletion + , inLocalTime = inLocalTime + , showUtcOffset = showUtcOffset + } + |> Expect.equal "" + , test "returns a utc completion string with no UTC offset if the format is ObsidianCardBoard" <| + \() -> + { time = Time.millisToPosix 0, zone = Time.customZone 0 [] } + |> TimeWithZone.completionString DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = False + , showUtcOffset = False + } + |> Expect.equal "@completed(1970-01-01T00:00:00)" + , test "returns a local completion string with an UTC offset if the format is ObsidianCardBoard" <| + \() -> + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + |> TimeWithZone.completionString DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianCardBoard + , inLocalTime = True + , showUtcOffset = True + } + |> Expect.equal "@completed(1970-01-01T05:00:00+05:00)" + , fuzz2 Fuzz.bool Fuzz.bool "returns a completion string if the format is ObsidianTasks" <| + \inLocalTime showUtcOffset -> + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + |> TimeWithZone.completionString DataviewTaskCompletion.NoCompletion + { format = GlobalSettings.ObsidianTasks + , inLocalTime = inLocalTime + , showUtcOffset = showUtcOffset + } + |> Expect.equal "✅ 1970-01-01" + , fuzz2 Fuzz.bool Fuzz.bool "returns a completion string if the format is the default for ObsidianDataview" <| + \inLocalTime showUtcOffset -> + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + |> TimeWithZone.completionString DataviewTaskCompletion.default + { format = GlobalSettings.ObsidianDataview + , inLocalTime = inLocalTime + , showUtcOffset = showUtcOffset + } + |> Expect.equal "[completion:: 1970-01-01]" + , fuzz2 Fuzz.bool Fuzz.bool "returns a completion string if the format is a specified ObsidianDataview" <| + \inLocalTime showUtcOffset -> + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + |> TimeWithZone.completionString (DataviewTaskCompletion.Text "done") + { format = GlobalSettings.ObsidianDataview + , inLocalTime = inLocalTime + , showUtcOffset = showUtcOffset + } + |> Expect.equal "[done:: 1970-01-01]" + , fuzz2 Fuzz.bool Fuzz.bool "returns a completion string if the format is ObsidianDataview.Emoji" <| + \inLocalTime showUtcOffset -> + { time = Time.millisToPosix 0, zone = Time.customZone 300 [] } + |> TimeWithZone.completionString DataviewTaskCompletion.Emoji + { format = GlobalSettings.ObsidianDataview + , inLocalTime = inLocalTime + , showUtcOffset = showUtcOffset + } + |> Expect.equal "✅ 1970-01-01" + ] + + +toString : Test +toString = + describe "toString" + [ describe "as utc string" + [ describe "with no offset appended" + [ test "returns the date and time string when the zone offset is 0" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 0 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = False } + |> Expect.equal "2024-01-01T00:00:00" + , test "returns the date and time string when the zone offset is +60" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 60 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = False } + |> Expect.equal "2024-01-01T00:00:00" + , test "returns the date and time string when the zone offset is -300" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone -300 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = False } + |> Expect.equal "2024-01-01T00:00:00" + ] + , describe "with the offset appended" + [ test "appends a 'Z' on the end when the zone offset is 0" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 0 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = True } + |> Expect.equal "2024-01-01T00:00:00Z" + , test "appends a 'Z' on the end when the zone offset is +60" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 60 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = True } + |> Expect.equal "2024-01-01T00:00:00Z" + , test "appends a 'Z' on the end when the zone offset is e-300" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone -300 [] + } + |> TimeWithZone.toString { inLocalTime = False, showUtcOffset = True } + |> Expect.equal "2024-01-01T00:00:00Z" + ] + ] + , describe "as local time string" + [ describe "with no offset appended" + [ test "returns the date and time string when the zone offset is 0" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 0 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = False } + |> Expect.equal "2024-01-01T00:00:00" + , test "returns the date and time string when the zone offset is +60" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 60 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = False } + |> Expect.equal "2024-01-01T01:00:00" + , test "returns the date and time string when the zone offset is -300" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone -300 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = False } + |> Expect.equal "2023-12-31T19:00:00" + ] + , describe "with the offset appended" + [ test "appends a '+00:00' on the end when the zone offset is 0" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 0 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = True } + |> Expect.equal "2024-01-01T00:00:00+00:00" + , test "appends a '+01:00' on the end when the zone offset is +60" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone 60 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = True } + |> Expect.equal "2024-01-01T01:00:00+01:00" + , test "appends a '-05:00' on the end when the zone offset is -300" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone -300 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = True } + |> Expect.equal "2023-12-31T19:00:00-05:00" + , test "appends a '-05:30' on the end when the zone offset is -330" <| + \() -> + { time = Time.millisToPosix startOf2024 + , zone = Time.customZone -330 [] + } + |> TimeWithZone.toString { inLocalTime = True, showUtcOffset = True } + |> Expect.equal "2023-12-31T18:30:00-05:30" + ] + ] + ] diff --git a/typescript-tests/fileFilter.test.ts b/typescript-tests/fileFilter.test.ts new file mode 100644 index 00000000..4023d823 --- /dev/null +++ b/typescript-tests/fileFilter.test.ts @@ -0,0 +1,70 @@ +import { FileFilter } from "../typescript/fileFilter" +import { Filter } from "../typescript/types" + +describe('fileFilter', () => { + describe('isAllowed', () => { + test('returns true if there are no filters', async () => { + const filters: Filter[] = []; + const testPath = 'foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(true); + }); + + test('return true if there are non-matching filters', async () => { + const filters: Filter[] = [{ tag : "fileFilter", data : "bar.md" }]; + const testPath = 'foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(true); + }); + + test('returns false if there is a matching file filter', async () => { + const filters: Filter[] = [{ tag : "fileFilter", data : "foo.md" }]; + const testPath = 'foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(false); + }); + + test('raturns false if there is a matching path filter', async () => { + const filters: Filter[] = [{ tag : "pathFilter", data : "aFolder" }]; + const testPath = 'aFolder/foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(false); + }); + + test('raturns false if there is a deeper matching path filter', async () => { + const filters: Filter[] = [{ tag : "pathFilter", data : "aFolder/bFolder" }]; + const testPath = 'aFolder/bFolder/cFolder/foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(false); + }); + + test('raturns true if there is a file with the name of the path in a path filter', async () => { + const filters: Filter[] = [{ tag : "pathFilter", data : "aFolder/bFolder" }]; + const testPath = 'aFolder/bFolder'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(true); + }); + + test('raturns true if there is a file in a parent path of a path filter', async () => { + const filters: Filter[] = [{ tag : "pathFilter", data : "aFolder/bFolder" }]; + const testPath = 'aFolder/foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(true); + }); + + test('ignores tag filters', async () => { + const filters: Filter[] = [{ tag : "tagFilter", data : "foo.md" }]; + const testPath = 'foo.md'; + const fileFilter = new FileFilter(filters); + + expect(fileFilter.isAllowed(testPath)).toEqual(true); + }); + }); +}); diff --git a/typescript/fileFilter.ts b/typescript/fileFilter.ts new file mode 100644 index 00000000..51d3debc --- /dev/null +++ b/typescript/fileFilter.ts @@ -0,0 +1,22 @@ +import { Filter } from "./types" + +export class FileFilter { + private excludedPaths: string[]; + + constructor(filters: Filter[]) { + this.buildExcludes(filters); + } + + isAllowed(path: string): boolean { + for (let elem of this.excludedPaths) { + if (path.includes(elem)) return false; + } + return true; + } + + private buildExcludes(filters: Filter[]) { + this.excludedPaths = filters + .filter(f => f.tag != "tagFilter") + .map(f => f.tag == "fileFilter" ? f.data : f.data + "/"); + } +} diff --git a/typescript/main.ts b/typescript/main.ts index cff4ec68..cff714c3 100644 --- a/typescript/main.ts +++ b/typescript/main.ts @@ -1,7 +1,6 @@ import { App, Modal, Notice, Plugin, PluginSettingTab, Setting, addIcon, normalizePath } from 'obsidian'; import { CardBoardView, VIEW_TYPE_CARD_BOARD } from './view'; - -export type CardBoardPluginSettings = CardBoardPluginSettingsPreV11 | CardBoardPluginSettingsPostV11; +import { CardBoardPluginSettings, CardBoardPluginSettingsPostV11 } from './types'; export default class CardBoardPlugin extends Plugin { private commandIds: string[] = []; @@ -113,125 +112,3 @@ export default class CardBoardPlugin extends Plugin { } } } - -export type CardBoardPluginSettingsPostV11 = { - data : { - boardConfigs : ({ - columns : ({ - tag : "completed" - data : { - collapsed : boolean; - name : string; - index : number; - limit : number; - } - } | { - tag : "dated" - data : { - collapsed : boolean; - name : string; - range : ({ - tag : "after" - data : number - } | { - tag : "before" - data : number - } | { - tag : "between" - data : { - from : number - to : number - } - }) - } - } | { - tag : "namedTag" - data : { - collapsed : boolean; - name : string; - tag : string; - } - } | { - tag : "otherTags" - data : { - collapsed : boolean; - name : string; - } - } | { - tag : "undated" - data : { - collapsed : boolean; - name : string; - } - } | { - tag : "untagged" - data : { - collapsed : boolean; - name : string; - } - })[]; - filters : ({ data : string; tag : "tagFilter" } | { data : string; tag : "pathFilter" } | { data : string; tag : "fileFilter" })[]; - filterPolarity : "Allow" | "Deny"; - showColumnTags : boolean; - showFilteredTags : boolean; - name : string - })[]; - globalSettings : { - taskCompletionFormat : "NoCompletion" | "ObsidianCardBoard" | "ObsidianDataview" | "ObsidianTasks"; - defaultColumnNames : { - today : string; - tomorrow : string; - future : string; - undated : string; - otherTags : string; - untagged : string - completed : string; - } - ignoreFileNameDates : boolean; - } - }; - version : string -} - -type CardBoardPluginSettingsPreV11 = { - data : { - boardConfigs : ( - { data : { - columns : { displayTitle : string; tag : string }[]; - showColumnTags : boolean; - completedCount : number; - filters : ({ data : string; tag : "tagFilter" } | { data : string; tag : "pathFilter" } | { data : string; tag : "fileFilter" })[]; - filterPolarity : "Allow" | "Deny"; - showFilteredTags : boolean; - includeOthers : boolean; - includeUntagged : boolean; - title : string - }; - tag : "tagBoardConfig" } - | { data : { - completedCount : number; - filters : ({ data : string; tag : "tagFilter" } | { data : string; tag : "pathFilter" } | { data : string; tag : "fileFilter" })[]; - filterPolarity : "Allow" | "Deny"; - showFilteredTags : boolean; - includeUndated : boolean; - title : string - }; - tag : "dateBoardConfig" - } - )[]; - globalSettings : { - taskCompletionFormat : "NoCompletion" | "ObsidianCardBoard" | "ObsidianDataview" | "ObsidianTasks"; - columnNames : { - today : string; - tomorrow : string; - future : string; - undated : string; - others : string; - untagged : string - completed : string; - } - ignoreFileNameDates : boolean; - } - }; - version : string -} diff --git a/typescript/types.ts b/typescript/types.ts new file mode 100644 index 00000000..b3f586d9 --- /dev/null +++ b/typescript/types.ts @@ -0,0 +1,128 @@ +export type CardBoardPluginSettings = CardBoardPluginSettingsPreV11 | CardBoardPluginSettingsPostV11; + +export type CardBoardPluginSettingsPostV11 = { + data : { + boardConfigs : ({ + columns : ({ + tag : "completed" + data : { + collapsed : boolean; + name : string; + index : number; + limit : number; + } + } | { + tag : "dated" + data : { + collapsed : boolean; + name : string; + range : ({ + tag : "after" + data : number + } | { + tag : "before" + data : number + } | { + tag : "between" + data : { + from : number + to : number + } + }) + } + } | { + tag : "namedTag" + data : { + collapsed : boolean; + name : string; + tag : string; + } + } | { + tag : "otherTags" + data : { + collapsed : boolean; + name : string; + } + } | { + tag : "undated" + data : { + collapsed : boolean; + name : string; + } + } | { + tag : "untagged" + data : { + collapsed : boolean; + name : string; + } + })[]; + filters : Filter[]; + filterPolarity : "Allow" | "Deny"; + showColumnTags : boolean; + showFilteredTags : boolean; + name : string + })[]; + globalSettings : { + defaultColumnNames : { + today : string; + tomorrow : string; + future : string; + undated : string; + otherTags : string; + untagged : string + completed : string; + } + filters : Filter[]; + ignoreFileNameDates : boolean; + taskCompletionFormat : "NoCompletion" | "ObsidianCardBoard" | "ObsidianDataview" | "ObsidianTasks"; + taskCompletionInLocalTime : boolean; + taskCompletionShowUtcOffset : boolean; + } + }; + version : string +} + +type CardBoardPluginSettingsPreV11 = { + data : { + boardConfigs : ( + { data : { + columns : { displayTitle : string; tag : string }[]; + showColumnTags : boolean; + completedCount : number; + filters : ({ data : string; tag : "tagFilter" } | { data : string; tag : "pathFilter" } | { data : string; tag : "fileFilter" })[]; + filterPolarity : "Allow" | "Deny"; + showFilteredTags : boolean; + includeOthers : boolean; + includeUntagged : boolean; + title : string + }; + tag : "tagBoardConfig" } + | { data : { + completedCount : number; + filters : Filter[]; + filterPolarity : "Allow" | "Deny"; + showFilteredTags : boolean; + includeUndated : boolean; + title : string + }; + tag : "dateBoardConfig" + } + )[]; + globalSettings : { + taskCompletionFormat : "NoCompletion" | "ObsidianCardBoard" | "ObsidianDataview" | "ObsidianTasks"; + columnNames : { + today : string; + tomorrow : string; + future : string; + undated : string; + others : string; + untagged : string + completed : string; + } + ignoreFileNameDates : boolean; + } + }; + version : string +} + +export type Filter = { data : string; tag : "tagFilter" } | { data : string; tag : "pathFilter" } | { data : string; tag : "fileFilter" }; diff --git a/typescript/view.ts b/typescript/view.ts index 4ca7ecb3..b4751999 100644 --- a/typescript/view.ts +++ b/typescript/view.ts @@ -14,16 +14,18 @@ import { import { Elm, ElmApp, Flags } from '../src/Main'; import CardBoardPlugin from './main'; -import { CardBoardPluginSettings, CardBoardPluginSettingsPostV11 } from './main'; +import { CardBoardPluginSettingsPostV11 } from './types'; import { getDateFromFile, IPeriodicNoteSettings } from 'obsidian-daily-notes-interface'; +import { FileFilter } from './fileFilter' export const VIEW_TYPE_CARD_BOARD = "card-board-view"; export class CardBoardView extends ItemView { - private vault: Vault; - private plugin: CardBoardPlugin; - private elm: ElmApp; - private elmDiv: any; + private vault: Vault; + private plugin: CardBoardPlugin; + private elm: ElmApp; + private elmDiv: any; + private fileFilter: FileFilter; constructor( plugin: CardBoardPlugin, @@ -44,7 +46,15 @@ export class CardBoardView extends ItemView { } async onOpen() { - this.icon = "card-board" + this.icon = "card-board" + + const globalSettings : any = this.plugin.settings?.data.globalSettings; + + if ((!(globalSettings === undefined)) && globalSettings.hasOwnProperty('filters')) { + this.fileFilter = new FileFilter(globalSettings.filters); + } else { + this.fileFilter = new FileFilter([]); + } // @ts-ignore const dataviewSettings = this.app.plugins.getPlugin("dataview")?.settings @@ -218,7 +228,7 @@ export class CardBoardView extends ItemView { if (element instanceof HTMLElement) { element.innerHTML = ""; - MarkdownRenderer.renderMarkdown(item.markdown, element, card.filePath, that.plugin); + MarkdownRenderer.render(that.app, item.markdown, element, card.filePath, that); const internalLinks = Array.from(element.getElementsByClassName("internal-link")); @@ -263,12 +273,13 @@ export class CardBoardView extends ItemView { } async handleElmInitialized() { - const markdownFiles = this.vault.getMarkdownFiles(); + const filteredFiles = markdownFiles.filter((file) => this.fileFilter.isAllowed(file.path)); - for (const file of markdownFiles) { + for (const file of filteredFiles) { const fileDate = this.formattedFileDate(file); const fileContents = await this.vault.cachedRead(file); + this.elm.ports.interopToElm.send({ tag: "fileAdded", data: { @@ -496,22 +507,23 @@ export class CardBoardView extends ItemView { }); } - async handleFileCreated( file: TAbstractFile ) { if (file instanceof TFile) { - const fileDate = this.formattedFileDate(file); - const fileContents = await this.vault.read(file); - - this.elm.ports.interopToElm.send({ - tag: "fileAdded", - data: { - filePath: file.path, - fileDate: fileDate, - fileContents: fileContents - } - }); + if (this.fileFilter.isAllowed(file.path)) { + const fileDate = this.formattedFileDate(file); + const fileContents = await this.vault.read(file); + + this.elm.ports.interopToElm.send({ + tag: "fileAdded", + data: { + filePath: file.path, + fileDate: fileDate, + fileContents: fileContents + } + }); + } } } @@ -519,8 +531,6 @@ export class CardBoardView extends ItemView { file: TAbstractFile ) { if (file instanceof TFile) { - const fileDate = this.formattedFileDate(file); - this.elm.ports.interopToElm.send({ tag: "fileDeleted", data: file.path @@ -532,17 +542,19 @@ export class CardBoardView extends ItemView { file: TAbstractFile ) { if (file instanceof TFile) { - const fileDate = this.formattedFileDate(file); - const fileContents = await this.vault.read(file); - - this.elm.ports.interopToElm.send({ - tag: "fileUpdated", - data: { - filePath: file.path, - fileDate: fileDate, - fileContents: fileContents - } - }); + if (this.fileFilter.isAllowed(file.path)) { + const fileDate = this.formattedFileDate(file); + const fileContents = await this.vault.read(file); + + this.elm.ports.interopToElm.send({ + tag: "fileUpdated", + data: { + filePath: file.path, + fileDate: fileDate, + fileContents: fileContents + } + }); + } } } @@ -550,13 +562,31 @@ export class CardBoardView extends ItemView { file: TAbstractFile, oldPath: string ) { - this.elm.ports.interopToElm.send({ - tag: "fileRenamed", - data: { - oldPath: oldPath, - newPath: file.path + let oldNew : [boolean, boolean] = [this.fileFilter.isAllowed(oldPath), this.fileFilter.isAllowed(file.path)]; + + switch(oldNew.join(",")) { + case 'false,true': { + this.handleFileCreated(file) + break; } - }); + case 'true,false': { + this.elm.ports.interopToElm.send({ + tag: "fileDeleted", + data: oldPath + }); + break; + } + case 'true,true': { + this.elm.ports.interopToElm.send({ + tag: "fileRenamed", + data: { + oldPath: oldPath, + newPath: file.path + } + }); + break; + } + } } // HELPERS