From 41e5030899cc5be54c9242b3ef197640230302cf Mon Sep 17 00:00:00 2001 From: Michael Herrmann Date: Mon, 12 Sep 2022 18:26:25 -0700 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4485a493a60d1eda68d7aa8c928aa58a4df5500a Author: Michael Herrmann Date: Mon Sep 12 18:03:57 2022 -0700 fix node WebGLRenderingContext commit 6f7960c5bfc3f7f87d3d9cc1ec1952128851cacd Merge: 60ab3b376 da993226d Author: Michael Herrmann Date: Fri Sep 9 14:45:27 2022 -0700 Merge branch 'dev' of github.com:michaeljherrmann/pixijs into dev commit da993226df64b804a9c00ed9ee4d011191467b8a Author: Matt Karl Date: Fri Sep 9 11:59:45 2022 -0400 v7.0.0-alpha commit 8c3bbaf2b2c6aa1bcdbb5c086e3548700e2777e9 Author: Matt Karl Date: Fri Sep 9 10:28:36 2022 -0400 Update package-lock.json, fix internal dependencies commit 1786b8f8b6423c5d3a75b6ebfb717cdee7564a1e Merge: b9d624e94 28e6b2841 Author: Matt Karl Date: Fri Sep 9 10:19:54 2022 -0400 Merge branch 'dev' into next commit 28e6b2841a65837a5e2873a3d5a9c27cabbe795a Author: Matt Karl Date: Fri Sep 9 09:48:31 2022 -0400 v6.5.3 commit b9d624e947ebecaa25bcebfe6026e8f9abd66d39 Merge: 8d717a590 0ec50af39 Author: Matt Karl Date: Thu Sep 8 13:21:17 2022 -0400 Merge branch 'dev' into next commit 0ec50af39f02ae24c9159045d8fd3a1c2b8bbca0 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Sep 8 18:20:51 2022 +0100 Fix injectGlobalMixins script (#8634) commit 8d717a590850375f1b755ff220dbbae5327d4697 Author: Matt Karl Date: Thu Sep 8 10:39:11 2022 -0400 Abandon the usage of peerDependencies (#8630) commit 7d9aed6392328a7fff40f204178256f806cd8a4d Merge: c4b13229f c1db3d819 Author: Matt Karl Date: Wed Sep 7 12:46:44 2022 -0400 Merge branch 'dev' into next commit c1db3d819ceaf44d17c0108757ec9e7856967b82 Author: dev7355608 Date: Wed Sep 7 15:03:29 2022 +0200 Cache sampler uniform values (#8587) commit d99d149eaae1b697ed4057c0813ddc23ce9507a9 Author: dev7355608 Date: Wed Sep 7 15:02:46 2022 +0200 Allow integer as sampler uniform value (#8586) commit c4b13229f9b66eceb64b5db0073b0c269770abb4 Author: Matt Karl Date: Wed Sep 7 09:01:50 2022 -0400 Remove browser builds for packages (#8626) commit 5823bec73949aba4c43609a53561c006af7f2517 Author: Matt Karl Date: Thu Sep 1 12:51:47 2022 -0400 Cleanup Core Dependencies (#8619) commit 6e0272fe93dbe49f1d160a62525c74431f2a4bf9 Merge: bb4e2fa20 db99845f5 Author: Matt Karl Date: Fri Aug 26 11:44:02 2022 -0400 Merge branch 'dev' into next commit db99845f538314161b5427f137571a500cdc906e Author: Samuel Maycock Date: Fri Aug 26 16:43:07 2022 +0100 Fix CanvasSpriteRenderer to render sprites with rotated BaseTextures (#8615) commit bb4e2fa20b765d50344ca017e2a3d4b5c20ded6a Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Fri Aug 26 15:08:38 2022 +0100 Decentralize Asset extensions, remove Loader (#8616) commit e169d5bf70be61505c80c6210e4355dad14d480c Merge: 0b4e269b9 cdec60770 Author: Matt Karl Date: Thu Aug 25 16:05:16 2022 -0400 Merge branch 'dev' into next commit cdec607704746db4f90182d9090865b839bcf05b Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Aug 25 21:03:51 2022 +0100 Fix split bitmap font loading (#8617) commit f74f1816086510f9e36dd6ff3a185ca8f70dded5 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Aug 25 15:51:00 2022 +0100 Fix Assets relative path matching (#8614) commit 28da8e704aecaacdca72cb387beb495462aa5c0e Author: Stafford Williams Date: Thu Aug 25 23:39:42 2022 +1000 Fix grammar on InteractionManager documentation (#8609) commit 0b4e269b92736839144bbbff7f0f6ea18e1841ac Merge: 72c77c2bf 48ab2f2d0 Author: Matt Karl Date: Wed Aug 24 09:59:36 2022 -0400 Merge branch 'dev' into next commit 48ab2f2d009bfb541079ef169df79e4174930f0a Author: Matt Karl Date: Wed Aug 24 09:43:00 2022 -0400 v6.5.2 commit 4ccb3be5ff86c54d711d0d43bdee647a67ea8af5 Merge: d38270fd9 4b86c2770 Author: Matt Karl Date: Wed Aug 24 09:36:25 2022 -0400 Merge branch 'dev' commit 72c77c2bf5f88780191100f1a887fe77b31b214f Merge: 1f6cf8594 4b86c2770 Author: Matt Karl Date: Tue Aug 23 14:03:47 2022 -0400 Merge branch 'dev' into next commit 4b86c2770f8e7952a1de87f313721fb3eba04b20 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue Aug 23 19:01:59 2022 +0100 Add cross-compatible path utils for Assets (#8605) commit c9e43d3fa99c8e678e13547a80358db149577c44 Author: Talha Özdemir <37840852+talhaozdemir@users.noreply.github.com> Date: Tue Aug 9 17:17:47 2022 +0300 Add support for base64 images with Assets (#8559) commit fdbdc45b6a95bd47145e3a7267fe2a69a1be4ebb Author: Dominik Frankowicz Date: Fri Aug 12 17:19:50 2022 +0200 Add pixijselementals.com to "Learn" section of main readme (#8581) commit 27889a1e75d01c237cda729f39d4b457fb810e28 Author: Nicholas Welch Date: Fri Aug 12 11:17:50 2022 -0400 Fix implementing test "should load texture array correctly" (#8578) commit fca5a8eb36d679445ed1ae67c32671b711c193bd Author: ryiwamoto Date: Sat Aug 13 00:16:49 2022 +0900 Fix documentations for PIXI.DisplayObject#childRemoved (#8582) commit 1f6cf8594af77edec63a4af1afcb7e1f338d277b Author: Matt Karl Date: Fri Aug 12 11:16:05 2022 -0400 Explicitly prioritize the LoaderParser extensions (#8577) commit 02c6d7034d77ac7b83c9cfd713796284b94ddfe2 Merge: be10876bf ac965dd59 Author: Matt Karl Date: Thu Aug 11 12:11:04 2022 -0400 Merge branch 'dev' into next commit ac965dd593f766a19ba9592e538a47f936f51739 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Aug 10 22:13:21 2022 +0100 Add missing SVG loader to Assets (#8574) commit be10876bfb925b9e843a6057ee21bf1c94c68280 Merge: 4975264a6 3c205ce9c Author: Matt Karl Date: Wed Aug 10 12:29:52 2022 -0400 Merge branch 'dev' into next commit 3c205ce9c853c4d4ab07521b48e01d84512c48de Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Aug 10 17:23:27 2022 +0100 Fix Assets' onProgress with multiple bundles (#8565) commit 0b06a7d962f995279d1827822c162e72d5d33a72 Author: Matt Karl Date: Wed Aug 10 12:22:27 2022 -0400 Fix Assets' text-based loading of fnt BitmapFonts (#8568) commit 6f136de4cc979f9f2619b43d5093ce709897e8b7 Author: Serhii Hrebeniuk <68051849+grebinka@users.noreply.github.com> Date: Wed Aug 10 18:00:46 2022 +0300 Fix jittering caused by incorrect BitmapText text width (#8536) commit e514f6555b3b05e5bec0f9545c0a8ee42c4f21a6 Author: Nicholas Welch Date: Wed Aug 10 10:59:26 2022 -0400 Fix typo in Resolver basePath setter (#8569) commit e02c696c40c75a154cb89d1bb1cdb12eb75952e3 Author: Mark Hayes Date: Wed Aug 10 10:58:23 2022 -0400 Loosen Graphics.drawPolygon types to use IPointData (#8573) commit 4975264a6ec65121751cbee2ce2cc77a80d34b9a Author: Matt Karl Date: Tue Aug 9 11:08:41 2022 -0400 Refactor Extensions to Self-Install (#8558) commit cbd17ca7b3ba32acb729bf2e56699b16066d50fc Merge: ba4c9be98 eb64a3ee6 Author: Matt Karl Date: Tue Aug 9 10:25:08 2022 -0400 Merge branch 'dev' into next commit ba4c9be988ac80ec20e2de4de9d61c224070f44b Merge: 30e3c3ddb fd9c9305b Author: Matt Karl Date: Tue Aug 9 10:23:59 2022 -0400 Merge branch 'dev' into next commit eb64a3ee623651f3d6f3ccba0591ae00551f857c Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue Aug 9 15:18:56 2022 +0100 Add installation error help to readme (#8563) commit d38270fd9354cfcfbcbff2fb8f6e0a9f42540cf5 Author: Talha Özdemir <37840852+talhaozdemir@users.noreply.github.com> Date: Tue Aug 9 17:17:47 2022 +0300 Add support for base64 images with Assets (#8559) commit fd9c9305b5722e09d8e9b0927dd2b093668ced60 Author: Matt Karl Date: Mon Aug 1 11:04:09 2022 -0400 Update package-lock.json commit b0958613fae2f0d414ea49c32a4612ebda0b96dd Author: Matt Karl Date: Mon Aug 1 09:18:33 2022 -0400 Fix more uses of document.createElement('canvas') (#8523) commit 30e3c3ddb13f6747881dec983216da2e50e06d8d Author: Matt Karl Date: Mon Aug 1 09:18:33 2022 -0400 Fix more uses of document.createElement('canvas') (#8523) commit f6b20597d5a68de1821a50cd7b139a148a9e67a6 Author: Matt Karl Date: Sun Jul 24 17:01:20 2022 -0400 Fix core usage of extensions commit 12b10dabfdaf03750f6f8ceb11f6d51872bc336d Merge: 1721128a1 a344b58dc Author: Matt Karl Date: Sun Jul 24 16:57:57 2022 -0400 Merge branch 'dev' into next commit a344b58dc859e3a60f75d2dc95b7d45180c766d8 Author: Matt Karl Date: Sun Jul 24 16:42:14 2022 -0400 v6.5.1 commit 27365ba1fa1fd716b7aae25e95b22ee9d86b15d6 Author: Matt Karl Date: Sun Jul 24 16:29:31 2022 -0400 Hotfix: Make sure core isn't bundled in ticker, canvas-sprite, canvas-mesh (#8527) commit 1721128a11fc0e268574f2909d9bfc9710d5e7b3 Author: Matt Karl Date: Sat Jul 23 15:37:31 2022 -0400 Remove transpile hacks commit 7bfe4f7168a2c6c45506bdd5fe8a012bbcc0e44a Author: Matt Karl Date: Sat Jul 23 07:31:20 2022 -0400 Update package-lock.json commit c79f46ce7b96ed4d16c734694ac37146a6f42008 Merge: 0a986ca92 63b9f0c48 Author: Matt Karl Date: Sat Jul 23 07:29:39 2022 -0400 Merge branch 'dev' into next commit 63b9f0c48521d739e7758fc8ecab337b00ff64fc Author: Matt Karl Date: Fri Jul 22 14:19:24 2022 -0400 v6.5.0 commit bff5c47fdc90a7dd795b9bcff379316c15e3ec2b Author: Matt Karl Date: Fri Jul 22 11:36:10 2022 -0400 Move VERSION to core instead of bundle (#8520) commit 1db04bb06d7b6c4cef978ed696587e7201423816 Author: Julien Marcou Date: Thu Jul 21 17:58:31 2022 +0200 Fix LoaderResource tests (#8518) commit 6fc416e59e27c60a8dc538b05d45143caa289605 Author: Matt Karl Date: Thu Jul 21 09:54:55 2022 -0400 Fix app and ismobilejs typings (#8517) commit 611ca6ad1f8f59f7ea0578fd2a490f91232c6f9d Author: Matt Karl Date: Wed Jul 20 16:41:10 2022 -0400 v6.5.0-rc.4 commit c2bcc640e749b8c15d173ec32e7bef57c46169f6 Author: Matt Karl Date: Wed Jul 20 16:39:17 2022 -0400 Fix error with assets import path commit 002784184f2c03835567b87a212f0bd42d7c8386 Author: Matt Karl Date: Wed Jul 20 16:13:08 2022 -0400 v6.5.0-rc.3 commit 380906dfc75aa135b28ed0433617171048a11521 Author: Matt Karl Date: Wed Jul 20 13:59:20 2022 -0400 FIx extensions for esm modules to .mjs (#8505) commit 326fa79b561366dc0a2c7b746a1efedba61bc48b Author: Matt Karl Date: Tue Jul 19 12:45:20 2022 -0400 Adds exports to package.json in Assets (#8504) commit 97c6f6bc3ab7ef05853e5957953dfd8a96213247 Author: Matt Karl Date: Tue Jul 19 12:43:58 2022 -0400 Adds missing types commit 0a60c58dc173380e8c306405bcfb10ada0f460f7 Author: Sudhan <25459246+Nahdus@users.noreply.github.com> Date: Tue Jul 19 22:13:04 2022 +0530 Exports to assets package.json (#8504) commit 0a986ca92353323eb478b8b07a605802cd2dce43 Author: Matt Karl Date: Mon Jul 18 17:12:34 2022 -0400 Remove nextRoundedRectBehavior and nextLineHeightBehavior (#8501) commit 675b7aad8f6816115f538e939ffd568800f48099 Author: Julien Marcou Date: Mon Jul 18 21:43:32 2022 +0200 Fix Jest not exiting properly when killing the http server (#8513) Co-authored-by: Matt Karl commit b5dd4327cd0d92410ec6840af08eb21a3c56d6ce Author: Matt Karl Date: Mon Jul 18 08:07:12 2022 -0400 Fix bundle ismobilejs (#8506) commit 559e3df8de62740b9099532a9c4d3f6701829de4 Author: Matt Karl Date: Fri Jul 15 14:39:15 2022 -0400 v6.5.0-rc.2 commit 011feab8a7c3c7f6a57a2aebacc7a2db2538fb35 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Fri Jul 15 15:22:15 2022 +0100 Fixes Node not starting (#8497) commit ffa04c33ea7bb7d8cadfcee0bdff03cb8114472c Author: Carlos Llera <92301011+CarlosLleraMartin@users.noreply.github.com> Date: Fri Jul 15 16:21:30 2022 +0200 Fixes ReferenceError: Can't find variable: ImageBitmap (#8499) commit d81bedaee5e94c198a95c0bcbf52d6e86d50a0f2 Author: Matt Karl Date: Thu Jul 14 18:31:56 2022 -0400 Fix the hello world example for Node bundle (#8495) commit b92879837d8b9461fb324606335c0f814ec55465 Author: Matt Karl Date: Thu Jul 14 18:29:11 2022 -0400 Fix Rollup warning, ignore used node dependencies (#8493) commit 16005f83e7a6d87831ce84f8a6d460606a331ef6 Author: Matt Karl Date: Thu Jul 14 14:17:24 2022 -0400 v6.5.0-rc commit c0877e03afbc6fcd32730b4da6c50fc0204f443a Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Jul 14 16:49:48 2022 +0100 Chore: Add script to clean types (#8492) commit 4776c290a24f9cdce3fc1c8be19349f7450df20d Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Jul 14 15:11:38 2022 +0100 Add detection parsers to Assets (#8482) commit 9c6c2958b45539a44ebc2159d381bca8f23ce222 Merge: 84096a7d4 063870f24 Author: Matt Karl Date: Thu Jul 14 09:52:45 2022 -0400 Chore: Drop add/remove from resolvers/parsers/caches (#8488) remove add/remove parsers commit 063870f247218ab789e166de58a0ceae0aecf75e Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Thu Jul 14 13:58:04 2022 +0100 remove add/remove parsers commit 84096a7d4c82522a62ecf354f459d89277f8b903 Author: Matt Karl Date: Thu Jul 14 06:45:45 2022 -0400 Chore: Eliminate redundant handling code for extensions (#8485) commit 6ff95cee2d94e038a703eaff67fad3243fb4575b Author: Raymond Date: Wed Jul 13 18:12:00 2022 -0400 Fixes #7272 Cubemap resources not being reuploaded on GL context loss (#8479) commit a7f477d3cd8d3f91a94eea1514b98e51fa30cc01 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Jul 13 12:54:13 2022 +0100 Rename resolver parsers (#8483) commit e619a74a8ea4291157a3a2176b0c4805b1e076aa Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Jul 13 01:16:03 2022 +0100 First-Class Support for Rendering with Node.js (#8397) commit 001c2e15bbafd3cd71be4cca71867a618e3a4f3d Author: Matt Karl Date: Mon Jul 11 10:18:24 2022 -0400 Update lock file to include missing peers commit 7c94608b6fa6755bbcafb12c8f349bef19702f3e Author: Matt Karl Date: Sun Jul 10 07:03:59 2022 -0400 Chore: Remove Renderer cast in Accessibility (#8476) commit 444194a554997e8ed15e2d5cb8c50ff1967570be Author: Matt Karl Date: Sun Jul 10 07:03:17 2022 -0400 Chore: Improve autoDetectRenderer (#8475) commit 2e6255b250431766023395539ab54ca61f51f942 Author: dev7355608 Date: Sat Jul 9 21:55:44 2022 +0200 Chore: Upgrade to earcut 2.2.4 (#8478) commit f7c17dc2522ef79e6dc3f2cdefb61abc5c9d690d Author: Matt Karl Date: Fri Jul 8 12:03:10 2022 -0400 Target ES2017 for browsers and ES2020 for module distribution (#8472) commit 34d693b7206e02c1378e37e4a7c48a86341a7afb Author: Mat Groves Date: Fri Jul 8 07:58:51 2022 +0100 fix silly screen width / height mixup commit 7326aa5be3858d438ed6995d4207af0b4f8ad055 Author: Matt Karl Date: Thu Jul 7 11:03:16 2022 -0400 Remove InteractionManager, EventSystem as default (#8425) commit f49e403222e8193a329f703fd7ef813bae3583e6 Author: Matt Karl Date: Thu Jul 7 10:43:15 2022 -0400 Add missing import commit 10aaa20b34233de13fa22813402c4aacfdc46907 Merge: 9b82827f4 eff02999f Author: Matt Karl Date: Wed Jul 6 20:29:50 2022 -0400 Merge branch 'dev' into next commit eff02999f4b7f2a8dabe5078fe2f6f0be4bf096a Author: Mat Groves Date: Wed Jul 6 21:12:51 2022 +0100 Feature: Asset Package (modern alternative to Loader) (#8365) commit 9b82827f4469a7f2fca9f3575bb5e59aacf9b3a5 Author: Matt Karl Date: Tue Jul 5 17:22:38 2022 -0400 Fix import issue in canvas-renderer (#8469) commit 51b55fd3ed1c18f114e040b5da6806f103808d93 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Tue Jul 5 17:22:26 2022 +0100 Chore: Update readme (#8466) commit 0751174e524ca408638318e4b31c675435c9c061 Merge: 4cb7c4d88 06395ea0a Author: Matt Karl Date: Mon Jul 4 15:40:50 2022 -0400 Merge branch 'dev' into next commit 06395ea0ad2900ab600b336cc28ab8bf2ef23f3a Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Mon Jul 4 20:09:37 2022 +0100 Chore: Remove unused lib references from packages (#8463) commit 4cb7c4d887a218bfb3e0ccbca4e2f698159f5cec Merge: acd50f404 8ea91328a Author: Matt Karl Date: Fri Jul 1 10:25:03 2022 -0400 Merge branch 'dev' into next commit 8ea91328a1bf137e71569b5eae369215bc965fd6 Author: Matt Karl Date: Fri Jul 1 10:23:37 2022 -0400 Chore: Simplify extra TSConfig files (#8460) commit a13d800081a12a1699e6703a09886ebc0cfd8ccb Author: Julien Marcou Date: Thu Jun 30 20:00:07 2022 +0200 Fix incorrect `saturate` blend mode mapping (#8458) commit acd50f40462dc526685a859bff5bfcd3233ef635 Merge: d43f31a4c 85ba270dd Author: Matt Karl Date: Thu Jun 30 09:21:21 2022 -0400 Merge branch 'dev' into next commit 85ba270dd4941d1b479230e952e569936dd57a6b Author: Matt Karl Date: Thu Jun 30 09:19:21 2022 -0400 Chore: Remove unused tsconfig files (#8455) commit d43f31a4c95ae90e8d392e2b0804cf6b979cfff3 Merge: 9a025e585 de6353804 Author: Matt Karl Date: Mon Jun 27 10:00:47 2022 -0400 Merge branch 'dev' into next commit de63538047d615e7230b4300a2ed2f33f623e0e6 Author: Julien Marcou Date: Mon Jun 27 15:59:59 2022 +0200 Add generic typing for Container children (#8433) commit 9a025e585cb70cb2fd1ca4d12ded7a00085003d4 Merge: 18ebd1b5a 6846041dd Author: Matt Karl Date: Mon Jun 27 09:33:06 2022 -0400 Merge branch 'dev' into next commit 6846041dd8a2238c00a2164e5416cd90583aaad6 Author: Serhiy Yashchuk Date: Mon Jun 27 16:32:19 2022 +0300 Fix EventSystem issue when tap event never fires (#8439) commit 726cdaf972f0faabddc5ee5c2629229181d1efe7 Author: Milton Candelero Date: Mon Jun 27 10:26:28 2022 -0300 EventSystem always fire a pointertap after click or touch (#8431) commit 18ebd1b5ab647f366b52eb683f961562a05aaca5 Merge: b1ea76c49 5842e02f7 Author: Matt Karl Date: Fri Jun 24 15:34:20 2022 -0400 Merge pull request #8440 from pixijs/next-dev commit 5842e02f76989aae64b78ca747b74179f06278d7 Merge: b1ea76c49 9b724f289 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Fri Jun 24 19:56:33 2022 +0100 Merge branch 'dev' into next commit b1ea76c497be39a41eb53ae214b216047f4397f7 Author: Matt Karl Date: Fri Jun 24 10:20:07 2022 -0400 Convert Prepare, Extract to Systems (#8427) commit 9b724f289118ebbf9b4500fa3faab1e7aaaabd02 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Fri Jun 24 15:18:30 2022 +0100 Chore: Add consistent import type (#8434) commit 9794ece302bb5bbb4bcc84eab4adb0c43708c34c Author: Matt Karl Date: Thu Jun 23 09:05:10 2022 -0400 Chore: Convert systems into extensions (#8423) commit db2b7a2ea9644cd356403e2e9190850df419ed12 Merge: 5e33eb473 ffddc9d5c Author: Matt Karl Date: Wed Jun 22 13:47:47 2022 -0400 Merge pull request #8422 from pixijs/chore/dev Chore: merge dev into next commit f215d87878f42939812ca0d76fa0784163b94697 Author: dev7355608 Date: Wed Jun 22 19:44:20 2022 +0200 Add color masks (#8353) commit ffddc9d5c7aebe07485aef4d68144d365248ffaa Merge: 5e33eb473 d733e3060 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Jun 22 14:54:07 2022 +0100 Merge branch 'dev' into next commit d733e30604f820cca9739a1c0b7401a2f1c8affd Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Jun 22 14:40:44 2022 +0100 Chore: Convert Tests To Jest (#8411) commit 5e33eb473893d56e67189dc7e184c3e1372bdbbd Author: Matt Karl Date: Wed Jun 22 09:36:06 2022 -0400 Install BatchRenderer By Default (#8416) commit 38249157aa85f207a27264f3bf1273e1fa8e1927 Author: Matt Karl Date: Wed Jun 22 08:54:59 2022 -0400 Remove AbstractBatchRenderer and BatchPluginFactory (#8420) commit b84185751af8efd2eeb3579a5b5c3a43ccce815f Author: Matt Karl Date: Tue Jun 21 13:13:43 2022 -0400 Chore: nullish coalescing and optional chaining (#8419) commit 9feac0e9d7a6b625201e3f81f51a2e7100a500a1 Author: Matt Karl Date: Tue Jun 21 09:30:18 2022 -0400 Use startsWith and includes methods (#8418) commit aac23cd4b96e8bf219edd6c451157f05e7ea6383 Author: Matt Karl Date: Tue Jun 21 09:10:16 2022 -0400 Remove polyfills, ES6 output target by default (#8417) commit fb15c78a1f26756c07efaf264ad1f1b9e4dbd5d2 Author: Matt Karl Date: Tue Jun 21 08:56:09 2022 -0400 Remove v6 deprecations (#8415) commit 2399fdd1d30d7abd4c7acfd031b613fcbd82aa8f Author: Matt Karl Date: Mon Jun 20 20:25:02 2022 -0400 Update InteractionManager.ts commit 9428029fac859804a33feae7c85b20034a4d76bc Merge: ccc1516ce b98acb1b8 Author: Matt Karl Date: Mon Jun 20 20:24:18 2022 -0400 Merge branch 'dev' into next commit b98acb1b85ec8629942ac13cabf7d2d2c65c596a Author: Matt Karl Date: Mon Jun 20 15:34:30 2022 -0400 Feature Extensions API (#8410) commit 03f8b02c34a6b9d2784e605b89a970fd6494bb0c Author: CJ Gammon Date: Mon Jun 20 13:58:45 2022 -0500 Fix interactivity in ShadowDOM (#8406) commit 779cdd91af4c7868b5789cae39a1e68750b7f574 Author: Lukas Steinmetz Date: Mon Jun 20 20:58:05 2022 +0200 Fix CanvasSpriteRenderer behaving differently to WebGL (#8408) commit 57f64d8d50cc6a1eb2cfe771416b4a3696affa53 Author: Marton Date: Mon Jun 20 20:40:30 2022 +0200 Clarified docs with BaseTexture.fromBuffer default options (#8413) commit 60ab3b3760c43b8808d24e89e6b2b6dfbb0bc88c Merge: 7bc0f7126 5e900b787 Author: Michael Herrmann Date: Thu Jun 16 16:53:09 2022 -0700 Merge branch 'pixijs-dev' into dev commit 5e900b7870f183b153a582f995ef9e08e2a99285 Merge: 7bc0f7126 2ce609920 Author: Michael Herrmann Date: Thu Jun 16 16:52:36 2022 -0700 Merge branch 'dev' of https://github.com/pixijs/pixijs into pixijs-dev commit 7bc0f7126e59f6075b5a8a52c654c2511c82ae34 Merge: 7cfadbc7b a87bb8703 Author: Michael Herrmann Date: Tue Jun 7 14:35:59 2022 -0700 Merge branch 'dev' into dev commit 2ce609920f5dc3277ba1e2cae30123cfdd90bd29 Author: Matt Karl Date: Tue Jun 14 16:46:02 2022 -0400 Chore: Remove deprecation warnings in unit-tests (#8403) commit 84745b799f41c850d8213678e51a8110bf9b814b Author: Matt Karl Date: Tue Jun 14 16:44:53 2022 -0400 Change BasePrepare's upload to be Promise-based (#8401) commit de505507f66eecf6629177b28ee7aea8fabae0ae Author: dev7355608 Date: Tue Jun 14 22:44:17 2022 +0200 Fix interaction and events usage of MaskData (#8400) commit 9284ddf58699fbc7fc94c08b3b6c102a718adf3d Author: dev7355608 Date: Mon Jun 13 21:06:36 2022 +0200 Fix triangulation of circular shape with radius 0 (#8311) commit 4e1ab76071e13251c08ee1d81e8af307dfa63ba7 Author: Matt Karl Date: Mon Jun 13 12:31:40 2022 -0400 Deprecate Callback for Spritesheet.parse (#8396) commit 9aeaeb70fae81c8e95209443203cd6f6c86cffdf Author: dev7355608 Date: Mon Jun 13 18:30:39 2022 +0200 Fix Extract's and CanvasExtract's pixels and canvas frame parameter (#8388) commit fb6c197f780bb92415bd8bfad8a76000ff7d258c Author: dev7355608 Date: Mon Jun 13 18:23:49 2022 +0200 Fix scissor mask bugs (#8376) commit 3a3324af542f502cc3be1e1e6e12ff0ee28924c2 Author: dev7355608 Date: Mon Jun 13 18:21:41 2022 +0200 Calculate bounds of graphics geometry based on the vertices (#8343) commit 7cfadbc7bb7a7c3cc823fb65e8e1b1dabbddcc26 Author: Michael Herrmann Date: Tue Jun 7 14:34:37 2022 -0700 skipUpdate in getBounds when calculating scissor mask commit ccc1516cedb3561f04f283f57877b940f96a1640 Author: Mat Groves Date: Fri Jun 3 15:43:44 2022 +0100 Remove AbstractRenderer, move its functionality to Systems (#8331) * - create mutisample system - create base renderer (needs better name) - create plugin system * - split out webGL renderer into systems - created first pass of `IRenderer` interface - add init to `ISystem` - make destroy optinoal on `ISystem` * - convert canvas renderer to use systems - `CanvasmaskManager` converted to `CanvasmaskSystem` - renamed `BaseRenderer` to `SystemManager` - removed `AbstractRenderer` - created a `ISystemConfig` - created a `StartupSystem` * - fill out destroy functions for new systems - resolution getter performance pass * - fix up the destory methods so they run in reverse to the init methods * - move system to correct folders - move `IRenderableObject` and `IRenderableContainer` to `IRenderer` file * EventSystem * - system doc update for `renderer` * update generic plugin docs * webGL system documentation * final round of docs * final doc tweaks * docs for SystemManager * fix the interface locations for `IRenderingContext` * Update packages/accessibility/src/AccessibilityManager.ts Co-authored-by: Matt Karl * fix packages/core refes * learn to spell.. * final types fix! * docs and missing getters on renderer * feedback * added deprications.. * rename context to canvasContext * linto * tweak background constructor * more deprications * fix bad import * make blit an option when rendering to a renderTexture * test tweaks * fix tests * fix type * feedback * tweak doc for system * add #is_DEBUG * fix docs * Update packages/core/src/view/ViewSystem.ts Co-authored-by: Matt Karl * rename `RenderSystem` -> `ObjectRendererSystem` `viewSystem.view` -> `viewSystem.element` * remove cast * Update CanvasObjectRendererSystem.ts * merges * fix busted text * lint * tweak to IRenderer * oops * lint some more Co-authored-by: Matt Karl Co-authored-by: Zyie <24736175+Zyie@users.noreply.github.com> commit a87bb87036d5fb9119ee92fd9c3da23b5bb9424b Author: Matt Karl Date: Thu Jun 2 11:30:51 2022 -0400 v6.4.2 commit 9aae40b6b1d0d7d1578be33ffdbf8cdd1de29d3f Author: Matt Karl Date: Thu Jun 2 11:27:56 2022 -0400 Fix lint errors commit a9acf1bb047b956e0e5a9c9dbfc805677103a344 Author: Matt Karl Date: Thu Jun 2 11:22:13 2022 -0400 v6.4.1 commit 8042c006b4810d4920b80c218b210949b685a9fe Author: Lazar Ljubenović Date: Thu Jun 2 17:15:20 2022 +0200 Clarify that the object's mask must be in the subtree of its parent in the docs (#8378) commit a804d7f30975effb526543454054be3b87891b8f Author: Zach Wade Date: Thu Jun 2 11:12:04 2022 -0400 Fix: Resolves issue where "exports" broke Webpack (#8381) commit 524eb15911b6590ec3c61530076d81ecaca3cf57 Merge: 01bda795f e7eaa713b Author: Matt Karl Date: Wed Jun 1 17:11:13 2022 -0400 Merge branch 'dev' into next commit e7eaa713b6e0eeb335e90384aec778f5c99c60d5 Author: Matt Karl Date: Wed Jun 1 17:07:26 2022 -0400 v6.4.0 commit 01bda795f7e8752f9a2c409782006506e695417b Merge: 55ca37024 db74023f2 Author: Matt Karl Date: Wed Jun 1 15:53:29 2022 -0400 Merge branch 'dev' into next commit db74023f2f884f66cc81e3faf533831644a1add8 Author: Matt Karl Date: Wed Jun 1 14:28:24 2022 -0400 Chore: Flatten the packages structure (#8374) commit 8153970d072df9f3bc0109fde6e3d3c2236da01f Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed Jun 1 13:50:21 2022 +0100 Fix TypeScript issues in tests (#8370) commit be5acab3e89374cbe6468f28cca9badcd6e7b307 Author: Zach Wade Date: Tue May 31 08:34:15 2022 -0400 Chore: Add "types" and "exports" to package.json (#8371) commit cde15df7d38539bef853d821f2f41ec53d46763e Author: dev7355608 Date: Wed May 25 23:49:54 2022 +0200 Skip shapes with negative dimensions in buildCircle (#8310) commit db824181dc3dfffa0951fb8579282ba8e654cb3b Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed May 25 18:57:26 2022 +0100 Chore: improve documentation linting (#8342) commit c95b7d518d193c4cc411fceff2d26ddcec520429 Author: Zyie <24736175+Zyie@users.noreply.github.com> Date: Wed May 25 15:37:24 2022 +0100 Improve TypeScript ESLint rules (#8341) commit 45052e29c4bf58043a9972142b5750c9c722d53c Author: Aysen69 <76961750+Aysen69@users.noreply.github.com> Date: Mon May 23 17:55:03 2022 +0300 Adds resolution property in BitmapText (#8357) commit 55ca37024b6c308d7a1c50424734041cb6448e7a Author: dev7355608 Date: Thu May 19 15:14:48 2022 +0200 Auto-transform to identity when using generateTexture (#8349) commit f0bc7fc1b8e64a0c0ff4b6922651a487c6d33c8b Author: dev7355608 Date: Thu May 19 15:12:26 2022 +0200 Set PREFER_ENV default to WEBGL2 for all devices (#7974) commit f07f871522d9a921757fe789a0966171fe70aac3 Author: dev7355608 Date: Wed May 18 18:12:44 2022 +0200 Update color uniform of MeshMaterial if alpha mode changes (#8330) commit 0aa699ebf7a01bfb4514dd67c92b7ba7c134fdb6 Author: Jax Reiff Date: Wed May 18 09:11:35 2022 -0700 Fix for 'attributes is null' exception on mobile (#8344) commit 9e3adf071438730ac85bd883af07ae6ea299b94c Author: Shukant Pal Date: Tue May 17 08:34:00 2022 -0400 Add KTXLoader support for loading key-value data from texture (#8251) commit f07d003a78157c5caa399bd3d175fa3d32e2d58a Author: charlie Date: Wed May 11 16:20:31 2022 -0400 Add documentation for Spritesheet usage without Loader (#8321) commit 23ab209aa5de77b1a9f392306565885a18bf0eea Author: dev7355608 Date: Mon May 9 16:03:48 2022 +0200 Fix round line-join with extreme angles (#8325) commit 25f4bbb9070ebde0814499d7716b45c3a9044970 Merge: 169ac4138 870312956 Author: Matt Karl Date: Wed May 4 13:45:39 2022 -0400 Merge branch 'main' into dev commit 87031295631dcd7db3e24b99ed7ceb2c4f963a40 Author: Matt Karl Date: Wed May 4 13:39:38 2022 -0400 v6.3.2 commit 2e584fa0bf69f369e7c5668468ef2ce0fd1b8ce5 Author: Matt Karl Date: Wed May 4 11:02:10 2022 -0400 Hotfix cached OffscreenCanvas in TextMetrics (#8318) commit 169ac413811bd92f2e19c9e2cf762f81daf3163f Author: Matt Karl Date: Wed May 4 11:02:10 2022 -0400 Hotfix cached OffscreenCanvas in TextMetrics (#8318) commit f77d35de6a5a80e31ec2f1a52299dd5a818e3a0d Author: Milton Candelero Date: Wed May 4 11:16:46 2022 -0300 Fix Discord URL (#8319) commit 3e453c208183fe0b285f601427ca2020fb94f5ba Author: Milton Candelero Date: Wed May 4 11:16:46 2022 -0300 Fix Discord URL (#8319) commit b8754e3a77764cf07648698619c6653fcd882857 Author: dev7355608 Date: Wed May 4 15:51:45 2022 +0200 Fix Text updates to remove recursive transform update (#8314) commit 32584707a14d10fcafa0eb47e4ef644291d71cbb Author: nouhmaster <47368896+nouhmaster@users.noreply.github.com> Date: Tue May 3 15:34:30 2022 +0200 Add options to Extract pixels method (#8247) commit 2c2b605239420c24417bd244e2e4bf4837619590 Author: Shukant Pal Date: Tue May 3 08:32:49 2022 -0500 Chore: Upgrade to TypeScript 4.3.0 and make setters for ObservablePoints accept IPointData (#8274) commit b0bfad4ec1a8bd8b88024311e426fa426fd4e975 Author: Michael Herrmann Date: Tue May 3 06:30:55 2022 -0700 Fix DisplayObject destroyed flag and event (#8297) commit a520915d81f307c40fcbad5d877b0f2de465c4bf Author: Matt Karl Date: Tue May 3 09:14:24 2022 -0400 v6.3.1 commit c63e917a0e1cd57ee3403b9c0d9e4add83241204 Author: dev7355608 Date: Fri Apr 29 23:24:09 2022 +0200 Render to an empty filter texture if the filter source frame does not intersect the current source frame (#8091) commit 8cf0248f88e12f935b1f0a34f8ef85acfa33aa99 Author: Matt Karl Date: Fri Apr 29 11:47:32 2022 -0400 Chore: refactor DOM-based side effects (#8307) commit 0ca6025866e82484b314228483af5449108e40b5 Author: SergeiSomin <35801681+SergeiSomin@users.noreply.github.com> Date: Mon Apr 25 22:13:22 2022 +0200 Fix hardcoded pluginName for getting MAX_TEXTURES in Graphics (#8244) commit f288f68ed7e105bb1c1aa201c0f7783b7e917a63 Author: Matt Karl Date: Mon Apr 25 11:40:34 2022 -0400 Favor Discord for PixiJS community chat (#8298) commit df15d293c05ec8fc4c1ddf43308a708fadffed5c Author: AshsHub <42413984+AshsHub@users.noreply.github.com> Date: Mon Apr 25 16:35:50 2022 +0100 Fix Texture types to support CubeResource (#8301) commit 7b20ea9a497fc7245a7dddb7534dc08b6bc37fbf Author: Matt Karl Date: Thu Apr 21 15:22:18 2022 -0400 Extending the amount of times for stale (#8293) commit 80716b0e827cd6b1fe051e4a859f550f041a70a2 Author: dev7355608 Date: Mon Apr 11 15:21:48 2022 +0200 Fix bounds of polygon drawing without fill (#8239) commit 7a80ee9477361282031584d59191412acaa96a54 Author: dev7355608 Date: Mon Apr 11 14:55:20 2022 +0200 Fix documentation of Rectangle.intersection and Rectangle.union (#8240) --- .eslintrc.json | 92 +- .eslintrc.tests.json | 17 - .github/CONTRIBUTING.md | 10 +- .github/stale.yml | 4 +- .github/workflows/nodejs.yml | 4 +- .gitignore | 3 + .npmrc | 1 + README.md | 32 +- bundles/pixi.js-legacy/README.md | 14 +- bundles/pixi.js-legacy/package.json | 40 +- bundles/pixi.js-legacy/src/index.ts | 32 +- .../polyfill => bundles/pixi.js-node}/LICENSE | 0 bundles/pixi.js-node/README.md | 93 + bundles/pixi.js-node/package.json | 76 + .../src/adapter/NodeCanvasElement.ts | 318 + .../src/adapter/NodeCanvasResource.ts | 118 + bundles/pixi.js-node/src/adapter/adapter.ts | 61 + bundles/pixi.js-node/src/adapter/index.ts | 9 + .../src/adapter/loadNodeBase64.ts | 51 + .../src/adapter/loadNodeBitmapFont.ts | 198 + .../pixi.js-node/src/adapter/loadNodeFont.ts | 40 + .../src/adapter/loadNodeTexture.ts | 54 + bundles/pixi.js-node/src/adapter/polyfills.ts | 9 + bundles/pixi.js-node/src/index.ts | 59 + bundles/pixi.js/README.md | 12 +- bundles/pixi.js/package.json | 82 +- bundles/pixi.js/src/index.ts | 62 +- global.d.ts | 5 +- jest.config.js | 34 + lerna.json | 2 +- package-lock.json | 41784 ++++++++++------ package.json | 79 +- packages/accessibility/README.md | 5 +- packages/accessibility/package.json | 29 +- .../accessibility/src/AccessibilityManager.ts | 102 +- .../accessibility/src/accessibleTarget.ts | 15 +- .../test/AccessibilityManager.tests.ts | 52 +- .../test/accessibleTarget.tests.ts | 17 +- packages/app/README.md | 5 +- packages/app/global.d.ts | 8 +- packages/app/package.json | 27 +- packages/app/src/Application.ts | 39 +- packages/app/src/ResizePlugin.ts | 23 +- packages/app/src/index.ts | 6 +- packages/app/test/Application.tests.ts | 138 +- packages/assets/README.md | 10 + packages/assets/package.json | 49 + packages/assets/src/Assets.ts | 794 + packages/assets/src/BackgroundLoader.ts | 107 + packages/assets/src/cache/Cache.ts | 180 + packages/assets/src/cache/CacheParser.ts | 35 + packages/assets/src/cache/index.ts | 3 + .../src/cache/parsers/cacheTextureArray.ts | 25 + packages/assets/src/cache/parsers/index.ts | 2 + packages/assets/src/detections/index.ts | 12 + .../src/detections/parsers/detectAvif.ts | 24 + .../src/detections/parsers/detectDefaults.ts | 15 + .../src/detections/parsers/detectWebp.ts | 23 + .../assets/src/detections/parsers/index.ts | 3 + .../src/detections/utils/detectUtils.ts | 26 + packages/assets/src/detections/utils/index.ts | 1 + packages/assets/src/index.ts | 7 + packages/assets/src/loader/Loader.ts | 202 + packages/assets/src/loader/index.ts | 3 + .../assets/src/loader/parsers/LoaderParser.ts | 85 + .../src/loader/parsers/WorkerManager.ts | 155 + packages/assets/src/loader/parsers/index.ts | 6 + .../assets/src/loader/parsers/loadJson.ts | 28 + packages/assets/src/loader/parsers/loadTxt.ts | 28 + .../assets/src/loader/parsers/loadWebFont.ts | 107 + .../src/loader/parsers/textures/index.ts | 4 + .../src/loader/parsers/textures/loadSVG.ts | 58 + .../loader/parsers/textures/loadTexture.ts | 107 + .../parsers/textures/utils/checkExtension.ts | 14 + .../parsers/textures/utils/createTexture.ts | 16 + .../loader/parsers/textures/utils/index.ts | 2 + packages/assets/src/loader/types.ts | 13 + packages/assets/src/resolver/Resolver.ts | 544 + packages/assets/src/resolver/index.ts | 3 + packages/assets/src/resolver/parsers/index.ts | 1 + .../src/resolver/parsers/resolveTextureUrl.ts | 17 + packages/assets/src/resolver/types.ts | 66 + packages/assets/src/utils/convertToList.ts | 22 + .../src/utils/createStringVariations.ts | 55 + packages/assets/src/utils/index.ts | 3 + packages/assets/src/utils/isSingleItem.ts | 5 + packages/assets/test/assets.tests.ts | 364 + .../assets/test/assets/fonts/outfit.woff2 | Bin 0 -> 35084 bytes .../test/assets/json/asset-manifest-2.json | 52 + .../test/assets/json/asset-manifest.json | 47 + packages/assets/test/assets/json/test.json | 4 + .../test/assets/spritesheet/multi-pack-0.json | 48 + .../test/assets/spritesheet/multi-pack-0.png | Bin 0 -> 2435 bytes .../test/assets/spritesheet/multi-pack-1.json | 23 + .../test/assets/spritesheet/multi-pack-1.png | Bin 0 -> 69086 bytes .../test/assets/spritesheet/spritesheet.json | 55 + .../test/assets/spritesheet/spritesheet.png | Bin 0 -> 3463 bytes .../test/assets/svg}/logo.svg | 0 .../test/assets/textures/bunny-2.png} | Bin .../assets/test/assets/textures/bunny.png | Bin 0 -> 449 bytes .../assets/test/assets/textures/bunny.webp | Bin 0 -> 368 bytes .../assets/textures/profile-abel@0.5x.jpg | Bin 0 -> 3353 bytes .../assets/textures/profile-abel@0.5x.webp | Bin 0 -> 2082 bytes .../test/assets/textures/profile-abel@2x.jpg | Bin 0 -> 25571 bytes .../test/assets/textures/profile-abel@2x.webp | Bin 0 -> 20830 bytes packages/assets/test/cache.tests.ts | 82 + packages/assets/test/loader.tests.ts | 229 + packages/assets/test/resolver.tests.ts | 444 + packages/assets/test/sampleManifest.ts | 75 + packages/assets/test/sampleManifests.ts | 75 + packages/assets/test/utils.tests.ts | 35 + packages/basis/README.md | 5 +- packages/basis/package.json | 30 +- packages/basis/src/Basis.ts | 24 +- packages/basis/src/TranscoderWorker.ts | 23 +- packages/basis/src/TranscoderWorkerWrapper.ts | 16 +- packages/basis/src/index.ts | 8 +- .../{BasisLoader.ts => loader/BasisParser.ts} | 236 +- packages/basis/src/loader/detectBasis.ts | 16 + packages/basis/src/loader/index.ts | 3 + packages/basis/src/loader/loadBasis.ts | 69 + packages/basis/test/basis.tests.ts | 22 + packages/{loaders => canvas-display}/LICENSE | 0 .../{canvas => }/canvas-display/README.md | 0 packages/canvas-display/global.d.ts | 12 + .../{canvas => }/canvas-display/package.json | 26 +- .../canvas-display/src/Container.ts | 6 +- .../canvas-display/src/DisplayObject.ts | 2 +- .../{canvas => }/canvas-display/src/index.ts | 0 .../test/.eslintrc.json | 0 .../canvas-display/test/Container.tests.ts | 53 + .../{interaction => canvas-extract}/LICENSE | 0 packages/canvas-extract/README.md | 13 + packages/canvas-extract/global.d.ts | 7 + .../{canvas => }/canvas-extract/package.json | 31 +- .../canvas-extract/src/CanvasExtract.ts | 92 +- .../{canvas => }/canvas-extract/src/index.ts | 0 .../test/CanvasExtract.tests.ts | 67 + .../filter-noise => canvas-graphics}/LICENSE | 0 packages/canvas-graphics/README.md | 13 + packages/canvas-graphics/global.d.ts | 9 + .../{canvas => }/canvas-graphics/package.json | 33 +- .../src/CanvasGraphicsRenderer.ts | 47 +- .../canvas-graphics/src/Graphics.ts | 13 +- .../{canvas => }/canvas-graphics/src/index.ts | 0 .../canvas-graphics/src/utils/PolygonUtils.ts | 45 +- .../test/.eslintrc.json | 0 .../test/CanvasGraphicsRenderer.tests.ts | 14 +- .../test/PolygonUtils.tests.ts | 33 +- .../filter-fxaa => canvas-mesh}/LICENSE | 0 packages/canvas-mesh/README.md | 13 + packages/{canvas => }/canvas-mesh/global.d.ts | 12 +- .../{canvas => }/canvas-mesh/package.json | 34 +- .../canvas-mesh/src/CanvasMeshRenderer.ts | 32 +- packages/{canvas => }/canvas-mesh/src/Mesh.ts | 3 - .../canvas-mesh/src/MeshMaterial.ts | 1 - .../canvas-mesh/src/NineSlicePlane.ts | 7 +- .../canvas-mesh/src/SimpleMesh.ts | 1 - .../canvas-mesh/src/SimpleRope.ts | 1 - .../{canvas => }/canvas-mesh/src/index.ts | 0 .../{canvas => }/canvas-mesh/src/settings.ts | 3 +- .../canvas-mesh/test/.eslintrc.json | 0 .../canvas-mesh/test/NineSlicePlane.tests.ts | 20 +- .../LICENSE | 0 .../canvas-particle-container/README.md | 0 .../canvas-particle-container/package.json | 26 +- .../src/ParticleContainer.ts | 20 +- .../canvas-particle-container/src/index.ts | 0 .../LICENSE | 0 packages/canvas-prepare/README.md | 13 + packages/canvas-prepare/global.d.ts | 7 + .../{canvas => }/canvas-prepare/package.json | 29 +- .../canvas-prepare/src/CanvasPrepare.ts | 27 +- .../{canvas => }/canvas-prepare/src/index.ts | 0 .../filter-blur => canvas-renderer}/LICENSE | 0 .../{canvas => }/canvas-renderer/README.md | 0 .../{canvas => }/canvas-renderer/global.d.ts | 14 +- .../{canvas => }/canvas-renderer/package.json | 29 +- .../canvas-renderer/src/BaseTexture.ts | 3 +- .../src/CanvasContextSystem.ts | 228 + .../src/CanvasMaskSystem.ts} | 34 +- .../src/CanvasObjectRendererSystem.ts | 184 + .../canvas-renderer/src/CanvasRenderer.ts | 599 + .../canvas-renderer/src/canvasUtils.ts | 30 +- .../{canvas => }/canvas-renderer/src/index.ts | 5 +- .../src/utils/canUseNewCanvasBlendModes.ts | 20 +- .../src/utils/mapCanvasBlendModesToPixi.ts | 8 +- .../test/.eslintrc.json | 0 .../test/CanvasMaskManager.tests.ts | 39 +- .../test/CanvasRenderer.tests.ts | 26 +- .../LICENSE | 0 .../canvas-sprite-tiling/README.md | 0 packages/canvas-sprite-tiling/global.d.ts | 7 + .../canvas-sprite-tiling/package.json | 33 +- .../canvas-sprite-tiling/src/TilingSprite.ts | 18 +- .../canvas-sprite-tiling/src/index.ts | 0 .../canvas-text => canvas-sprite}/LICENSE | 0 packages/canvas-sprite/README.md | 13 + packages/canvas-sprite/global.d.ts | 8 + .../{canvas => }/canvas-sprite/package.json | 33 +- .../canvas-sprite/src/CanvasSpriteRenderer.ts | 85 +- .../{canvas => }/canvas-sprite/src/Sprite.ts | 13 +- .../{canvas => }/canvas-sprite/src/index.ts | 0 .../test/.eslintrc.json | 0 .../test/CanvasSpriteRenderer.tests.ts | 146 + .../canvas-sprite => canvas-text}/LICENSE | 0 packages/{canvas => }/canvas-text/README.md | 0 .../{canvas => }/canvas-text/package.json | 30 +- packages/{canvas => }/canvas-text/src/Text.ts | 1 - .../{canvas => }/canvas-text/src/index.ts | 0 packages/canvas/canvas-display/LICENSE | 21 - packages/canvas/canvas-display/global.d.ts | 5 - .../canvas-display/test/Container.tests.ts | 56 - packages/canvas/canvas-extract/README.md | 16 - .../test/CanvasExtract.tests.ts | 76 - packages/canvas/canvas-graphics/README.md | 16 - packages/canvas/canvas-graphics/global.d.ts | 7 - packages/canvas/canvas-mesh/README.md | 16 - packages/canvas/canvas-prepare/README.md | 16 - .../canvas-renderer/src/CanvasRenderer.ts | 494 - .../canvas/canvas-renderer/src/Renderer.ts | 31 - .../canvas/canvas-sprite-tiling/global.d.ts | 5 - packages/canvas/canvas-sprite/README.md | 16 - packages/canvas/canvas-sprite/global.d.ts | 6 - .../test/CanvasSpriteRenderer.tests.ts | 26 - packages/compressed-textures/README.md | 7 +- packages/compressed-textures/global.d.ts | 8 + packages/compressed-textures/package.json | 28 +- packages/compressed-textures/src/const.ts | 58 +- packages/compressed-textures/src/index.ts | 1 + .../src/loaders/CompressedTextureLoader.ts | 211 - .../src/loaders/KTXLoader.ts | 411 - .../loaders/compressedTextureExtensions.ts | 14 + .../src/loaders/detectCompressedTextures.ts | 78 + .../compressed-textures/src/loaders/index.ts | 8 +- .../src/loaders/loadDDS.ts | 58 + .../src/loaders/loadKTX.ts | 72 + .../src/loaders/registerCompressedTextures.ts | 63 - .../loaders/resolveCompressedTextureUrl.ts | 50 + .../compressed-textures/src/parsers/index.ts | 3 + .../DDSLoader.ts => parsers/parseDDS.ts} | 303 +- .../src/parsers/parseKTX.ts | 373 + .../src/resources/BlobResource.ts | 17 +- .../resources/CompressedTextureResource.ts | 24 +- .../test/compressed-textures.tests.ts | 90 + packages/constants/package.json | 19 +- packages/constants/src/index.ts | 286 +- packages/constants/test/constants.tests.ts | 55 +- packages/core/global.d.ts | 24 + packages/core/package.json | 33 +- packages/core/src/AbstractRenderer.ts | 464 - packages/core/src/IRenderableObject.ts | 31 - packages/core/src/IRenderer.ts | 119 + packages/core/src/IRenderingContext.ts | 9 - packages/core/src/ISystem.ts | 53 - packages/core/src/Renderer.ts | 799 +- packages/core/src/autoDetectRenderer.ts | 34 +- .../core/src/background/BackgroundSystem.ts | 127 + packages/core/src/batch/BatchDrawCall.ts | 1 - packages/core/src/batch/BatchGeometry.ts | 3 - packages/core/src/batch/BatchPluginFactory.ts | 94 - ...tractBatchRenderer.ts => BatchRenderer.ts} | 122 +- .../core/src/batch/BatchShaderGenerator.ts | 5 +- packages/core/src/batch/BatchSystem.ts | 20 +- packages/core/src/batch/BatchTextureArray.ts | 1 - packages/core/src/batch/ObjectRenderer.ts | 21 +- packages/core/src/context/ContextSystem.ts | 97 +- packages/core/src/context/WebGLExtensions.ts | 3 +- packages/core/src/deprecations.ts | 51 - packages/core/src/filters/Filter.ts | 22 +- packages/core/src/filters/FilterState.ts | 4 +- packages/core/src/filters/FilterSystem.ts | 85 +- .../filters/spriteMask/SpriteMaskFilter.ts | 8 +- packages/core/src/framebuffer/Framebuffer.ts | 6 - .../core/src/framebuffer/FramebufferSystem.ts | 41 +- .../core/src/framebuffer/GLFramebuffer.ts | 1 - .../core/src/framebuffer/MultisampleSystem.ts | 82 + packages/core/src/geometry/Attribute.ts | 2 - packages/core/src/geometry/Buffer.ts | 20 +- packages/core/src/geometry/BufferSystem.ts | 25 +- packages/core/src/geometry/Geometry.ts | 42 +- packages/core/src/geometry/GeometrySystem.ts | 30 +- packages/core/src/geometry/ViewableBuffer.ts | 4 +- .../geometry/utils/setVertexAttribArrays.ts | 2 +- packages/core/src/index.ts | 57 +- packages/core/src/mask/AbstractMaskSystem.ts | 4 +- packages/core/src/mask/MaskData.ts | 27 +- packages/core/src/mask/MaskSystem.ts | 92 +- packages/core/src/mask/ScissorSystem.ts | 33 +- packages/core/src/mask/StencilSystem.ts | 58 +- packages/core/src/plugin/PluginSystem.ts | 102 + .../core/src/projection/ProjectionSystem.ts | 27 +- .../core/src/render/ObjectRendererSystem.ts | 134 + .../src/renderTexture/BaseRenderTexture.ts | 5 +- .../renderTexture/GenerateTextureSystem.ts | 103 + .../core/src/renderTexture/RenderTexture.ts | 48 +- .../src/renderTexture/RenderTexturePool.ts | 15 +- .../src/renderTexture/RenderTextureSystem.ts | 31 +- packages/core/src/settings.ts | 8 +- packages/core/src/shader/GLProgram.ts | 2 - packages/core/src/shader/Program.ts | 4 - packages/core/src/shader/Shader.ts | 3 - packages/core/src/shader/ShaderSystem.ts | 38 +- packages/core/src/shader/UniformGroup.ts | 6 - .../utils/checkMaxIfStatementsInShader.ts | 2 +- .../core/src/shader/utils/compileShader.ts | 4 +- .../core/src/shader/utils/defaultValue.ts | 5 +- .../core/src/shader/utils/generateProgram.ts | 5 +- .../shader/utils/generateUniformBufferSync.ts | 11 +- .../src/shader/utils/generateUniformsSync.ts | 24 +- .../core/src/shader/utils/getAttributeData.ts | 6 +- .../core/src/shader/utils/getTestContext.ts | 9 +- .../core/src/shader/utils/getUniformData.ts | 4 +- .../core/src/shader/utils/logProgramError.ts | 2 - packages/core/src/shader/utils/mapSize.ts | 3 +- .../core/src/shader/utils/setPrecision.ts | 4 +- .../core/src/shader/utils/uniformParsers.ts | 6 +- .../src/shader/utils/unsafeEvalSupported.ts | 3 +- packages/core/src/startup/StartupSystem.ts | 62 + packages/core/src/state/State.ts | 9 - packages/core/src/state/StateSystem.ts | 36 +- .../state/utils/mapWebGLBlendModesToPixi.ts | 3 +- packages/core/src/system/ISystem.ts | 21 + packages/core/src/system/SystemManager.ts | 154 + packages/core/src/systems.ts | 6 + packages/core/src/textures/BaseTexture.ts | 84 +- packages/core/src/textures/GLTexture.ts | 1 - packages/core/src/textures/Texture.ts | 147 +- packages/core/src/textures/TextureGCSystem.ts | 24 +- packages/core/src/textures/TextureMatrix.ts | 14 +- packages/core/src/textures/TextureSystem.ts | 49 +- packages/core/src/textures/TextureUvs.ts | 2 - .../resources/AbstractMultiResource.ts | 29 +- .../src/textures/resources/ArrayResource.ts | 14 +- .../textures/resources/BaseImageResource.ts | 9 +- .../src/textures/resources/BufferResource.ts | 16 +- .../src/textures/resources/CanvasResource.ts | 6 +- .../src/textures/resources/CubeResource.ts | 20 +- .../src/textures/resources/DepthResource.ts | 4 +- .../textures/resources/ImageBitmapResource.ts | 6 +- .../src/textures/resources/ImageResource.ts | 23 +- .../core/src/textures/resources/Resource.ts | 30 +- .../src/textures/resources/SVGResource.ts | 16 +- .../src/textures/resources/VideoResource.ts | 35 +- .../textures/resources/autoDetectResource.ts | 16 +- .../utils/mapTypeAndFormatToInternalFormat.ts | 5 +- packages/core/src/utils/Quad.ts | 1 - packages/core/src/utils/QuadUv.ts | 5 +- packages/core/src/view/ViewSystem.ts | 141 + packages/core/test/ArrayResource.tests.ts | 51 +- packages/core/test/BaseTexture.tests.ts | 162 +- packages/core/test/BatchRenderer.tests.ts | 59 +- packages/core/test/CanvasResource.tests.ts | 50 +- packages/core/test/CubeResource.tests.ts | 20 +- packages/core/test/FilterSystem.tests.ts | 92 +- packages/core/test/FramebufferSystem.tests.ts | 292 +- packages/core/test/Geometry.tests.ts | 70 +- .../core/test/ImageBitmapResource.tests.ts | 43 +- packages/core/test/ImageResource.tests.ts | 129 +- packages/core/test/MaskSystem.tests.ts | 428 +- packages/core/test/ProjectionSystem.tests.ts | 29 +- packages/core/test/RenderTexture.tests.ts | 166 +- packages/core/test/RenderTexturePool.tests.ts | 37 +- .../core/test/RenderTextureSystem.tests.ts | 57 +- packages/core/test/Renderer.tests.ts | 97 +- packages/core/test/SVGResource.tests.ts | 167 +- packages/core/test/Shader.tests.ts | 41 +- packages/core/test/ShaderSystem.tests.ts | 24 +- packages/core/test/Texture.tests.ts | 315 +- packages/core/test/TextureSystem.tests.ts | 100 +- packages/core/test/UniformBuffer.tests.ts | 32 +- packages/core/test/VideoResource.tests.ts | 53 +- .../core/test/autoDetectResource.tests.ts | 55 +- packages/core/test/resources/cube-face.jpg | Bin 0 -> 6247 bytes packages/display/package.json | 27 +- packages/display/src/Bounds.ts | 28 +- packages/display/src/Container.ts | 108 +- packages/display/src/DisplayObject.ts | 148 +- packages/display/src/settings.ts | 3 +- packages/display/test/Container.tests.ts | 784 +- packages/display/test/DisplayObject.tests.ts | 239 +- packages/display/test/toGlobal.tests.ts | 15 +- packages/display/test/toLocal.tests.ts | 21 +- packages/events/README.md | 37 +- packages/events/global.d.ts | 15 + packages/events/package.json | 30 +- packages/events/src/EventBoundary.ts | 142 +- packages/events/src/EventSystem.ts | 119 +- packages/events/src/FederatedEvent.ts | 39 +- packages/events/src/FederatedEventTarget.ts | 97 +- packages/events/src/FederatedMouseEvent.ts | 44 +- packages/events/src/FederatedPointerEvent.ts | 15 +- packages/events/src/FederatedWheelEvent.ts | 1 - packages/events/test/EventBoundary.tests.ts | 81 +- packages/events/test/EventSystem.tests.ts | 129 +- .../canvas-extract => extensions}/LICENSE | 2 +- packages/extensions/README.md | 15 + packages/extensions/package.json | 35 + packages/extensions/src/index.ts | 257 + packages/extensions/test/extensions.tests.ts | 139 + packages/extract/README.md | 5 +- packages/extract/global.d.ts | 7 + packages/extract/package.json | 27 +- packages/extract/src/Extract.ts | 93 +- packages/extract/test/Extract.tests.ts | 57 +- .../LICENSE | 0 packages/{filters => }/filter-alpha/README.md | 0 .../{filters => }/filter-alpha/package.json | 26 +- .../filter-alpha/src/AlphaFilter.ts | 2 - .../{filters => }/filter-alpha/src/alpha.frag | 0 .../{filters => }/filter-alpha/src/index.ts | 0 .../filter-alpha/test/AlphaFilter.tests.ts | 25 + .../canvas-renderer => filter-blur}/LICENSE | 0 packages/{filters => }/filter-blur/README.md | 0 .../{filters => }/filter-blur/package.json | 27 +- .../filter-blur/src/BlurFilter.ts | 15 +- .../filter-blur/src/BlurFilterPass.ts | 8 +- .../filter-blur/src/generateBlurFragSource.ts | 3 +- .../filter-blur/src/generateBlurVertSource.ts | 0 .../filter-blur/src/getMaxBlurKernelSize.ts | 0 .../{filters => }/filter-blur/src/index.ts | 0 packages/filter-blur/test/BlurFilter.tests.ts | 32 + .../LICENSE | 0 .../filter-color-matrix/README.md | 0 .../filter-color-matrix/package.json | 26 +- .../src/ColorMatrixFilter.ts | 36 +- .../filter-color-matrix/src/colorMatrix.frag | 0 .../filter-color-matrix/src/index.ts | 0 .../test/ColorMatrixFilter.tests.ts | 17 +- .../LICENSE | 0 .../filter-displacement/README.md | 0 .../filter-displacement/package.json | 27 +- .../src/DisplacementFilter.ts | 8 +- .../filter-displacement/src/displacement.frag | 0 .../filter-displacement/src/displacement.vert | 0 .../filter-displacement/src/index.ts | 0 .../canvas-mesh => filter-fxaa}/LICENSE | 0 packages/{filters => }/filter-fxaa/README.md | 0 .../{filters => }/filter-fxaa/package.json | 26 +- .../filter-fxaa/src/FXAAFilter.ts | 2 - .../{filters => }/filter-fxaa/src/fxaa.frag | 0 .../{filters => }/filter-fxaa/src/fxaa.vert | 0 .../{filters => }/filter-fxaa/src/index.ts | 0 .../canvas-graphics => filter-noise}/LICENSE | 0 packages/{filters => }/filter-noise/README.md | 0 .../{filters => }/filter-noise/package.json | 26 +- .../filter-noise/src/NoiseFilter.ts | 2 - .../{filters => }/filter-noise/src/index.ts | 0 .../{filters => }/filter-noise/src/noise.frag | 0 .../filter-alpha/test/AlphaFilter.tests.ts | 26 - .../filter-blur/test/BlurFilter.tests.ts | 33 - packages/graphics-extras/package.json | 28 +- .../graphics-extras/src/drawChamferRect.ts | 4 +- .../graphics-extras/src/drawFilletRect.ts | 4 +- .../graphics-extras/src/drawRegularPolygon.ts | 4 +- .../graphics-extras/src/drawRoundedPolygon.ts | 4 +- packages/graphics-extras/src/drawStar.ts | 7 +- packages/graphics-extras/src/drawTorus.ts | 4 +- packages/graphics-extras/src/index.ts | 3 +- .../graphics-extras/test/Graphics.tests.ts | 46 +- packages/graphics/package.json | 32 +- packages/graphics/src/Graphics.ts | 168 +- packages/graphics/src/GraphicsData.ts | 7 +- packages/graphics/src/GraphicsGeometry.ts | 151 +- packages/graphics/src/const.ts | 24 +- packages/graphics/src/index.ts | 2 +- packages/graphics/src/styles/FillStyle.ts | 6 +- packages/graphics/src/styles/LineStyle.ts | 3 - packages/graphics/src/utils/ArcUtils.ts | 17 +- packages/graphics/src/utils/BatchPart.ts | 14 +- packages/graphics/src/utils/BezierUtils.ts | 5 +- .../graphics/src/utils/IShapeBuildCommand.ts | 3 +- packages/graphics/src/utils/QuadraticUtils.ts | 5 +- packages/graphics/src/utils/buildCircle.ts | 17 +- packages/graphics/src/utils/buildLine.ts | 22 +- packages/graphics/src/utils/buildPoly.ts | 7 +- packages/graphics/src/utils/buildRectangle.ts | 3 +- .../src/utils/buildRoundedRectangle.ts | 161 +- packages/graphics/src/utils/index.ts | 14 +- packages/graphics/test/Graphics.tests.ts | 540 +- packages/interaction/README.md | 16 - packages/interaction/global.d.ts | 9 - packages/interaction/package.json | 34 - packages/interaction/src/InteractionData.ts | 206 - packages/interaction/src/InteractionEvent.ts | 80 - .../interaction/src/InteractionManager.ts | 1920 - .../src/InteractionTrackingData.ts | 142 - packages/interaction/src/TreeSearch.ts | 200 - packages/interaction/src/index.ts | 5 - packages/interaction/src/interactiveTarget.ts | 162 - .../interaction/test/InteractionData.tests.ts | 28 - .../test/InteractionManager.tests.ts | 2174 - packages/interaction/test/MockPointer.ts | 323 - packages/loaders/README.md | 32 - packages/loaders/global.d.ts | 33 - packages/loaders/package.json | 32 - packages/loaders/src/AppLoaderPlugin.ts | 48 - packages/loaders/src/Loader.ts | 795 - packages/loaders/src/LoaderResource.ts | 1415 - packages/loaders/src/TextureLoader.ts | 47 - packages/loaders/src/base/AsyncQueue.ts | 299 - packages/loaders/src/base/Signal.ts | 236 - packages/loaders/src/base/encodeBinary.ts | 77 - packages/loaders/src/base/parseUri.ts | 39 - packages/loaders/src/index.ts | 14 - packages/loaders/src/middleware/caching.ts | 34 - packages/loaders/src/middleware/index.ts | 2 - packages/loaders/src/middleware/parsing.ts | 82 - .../loaders/test/AppLoaderPlugin.tests.ts | 34 - packages/loaders/test/AsyncQueue.tests.ts | 957 - packages/loaders/test/Loader.tests.ts | 163 - packages/loaders/test/LoaderBase.tests.ts | 951 - packages/loaders/test/LoaderResource.test.ts | 667 - packages/loaders/test/TextureLoader.tests.ts | 51 - packages/loaders/test/fixtureData.ts | 8 - packages/loaders/test/fixtures/data.ts | 8 - packages/loaders/test/fixtures/spritesheet.ts | 56 - packages/loaders/test/resources/data/hud.json | 92 - packages/loaders/test/resources/data/hud.png | Bin 509 -> 0 bytes .../loaders/test/resources/data/hud2.json | 92 - packages/loaders/test/resources/data/hud2.png | Bin 509 -> 0 bytes packages/loaders/test/resources/index.ts | 56 - packages/math-extras/global.d.ts | 17 +- packages/math-extras/package.json | 26 +- packages/math-extras/src/index.ts | 9 +- packages/math-extras/src/pointExtras.ts | 25 +- packages/math-extras/src/rectangleExtras.ts | 10 +- packages/math-extras/test/Point.tests.ts | 274 +- packages/math-extras/test/Rectangle.tests.ts | 120 +- packages/math-extras/test/floatEqual.tests.ts | 9 +- .../test/lineIntersection.tests.ts | 33 +- .../test/segmentIntersection.tests.ts | 40 +- packages/math/package.json | 19 +- packages/math/src/IPoint.ts | 4 +- packages/math/src/Matrix.ts | 54 +- packages/math/src/ObservablePoint.ts | 11 +- packages/math/src/Point.ts | 13 +- packages/math/src/Transform.ts | 13 +- packages/math/src/const.ts | 8 +- packages/math/src/groupD8.ts | 40 +- packages/math/src/shapes/Circle.ts | 15 +- packages/math/src/shapes/Ellipse.ts | 11 +- packages/math/src/shapes/Polygon.ts | 14 +- packages/math/src/shapes/Rectangle.ts | 33 +- packages/math/src/shapes/RoundedRectangle.ts | 8 +- packages/math/test/Circle.tests.ts | 75 +- packages/math/test/Ellipse.tests.ts | 81 +- packages/math/test/Matrix.tests.ts | 221 +- packages/math/test/ObservablePoint.tests.ts | 40 +- packages/math/test/Point.tests.ts | 43 +- packages/math/test/Polygon.tests.ts | 68 +- packages/math/test/Rectangle.tests.ts | 297 +- packages/math/test/RoundedRectangle.tests.ts | 73 +- packages/math/test/Transform.tests.ts | 65 +- packages/mesh-extras/README.md | 5 +- packages/mesh-extras/package.json | 30 +- packages/mesh-extras/src/NineSlicePlane.ts | 9 +- packages/mesh-extras/src/SimpleMesh.ts | 4 +- packages/mesh-extras/src/SimplePlane.ts | 5 +- packages/mesh-extras/src/SimpleRope.ts | 7 +- .../mesh-extras/src/geometry/RopeGeometry.ts | 11 +- .../mesh-extras/test/NineSlicePlane.tests.ts | 32 +- packages/mesh-extras/test/SimpleMesh.tests.ts | 18 +- .../mesh-extras/test/SimplePlane.tests.ts | 67 +- packages/mesh-extras/test/SimpleRope.tests.ts | 53 +- packages/mesh/README.md | 5 +- packages/mesh/package.json | 31 +- packages/mesh/src/Mesh.ts | 45 +- packages/mesh/src/MeshBatchUvs.ts | 2 - packages/mesh/src/MeshGeometry.ts | 6 +- packages/mesh/src/MeshMaterial.ts | 29 +- packages/mesh/test/Mesh.tests.ts | 92 +- packages/mixin-cache-as-bitmap/global.d.ts | 9 +- packages/mixin-cache-as-bitmap/package.json | 33 +- packages/mixin-cache-as-bitmap/src/index.ts | 55 +- .../test/cacheAsBitmap.tests.ts | 54 +- packages/mixin-get-child-by-name/global.d.ts | 5 +- packages/mixin-get-child-by-name/package.json | 26 +- packages/mixin-get-child-by-name/src/index.ts | 11 +- .../test/getChildByName.tests.ts | 44 +- .../mixin-get-global-position/package.json | 28 +- .../mixin-get-global-position/src/index.ts | 5 +- .../test/getGlobalPosition.tests.ts | 20 +- packages/particle-container/README.md | 5 +- packages/particle-container/package.json | 31 +- .../particle-container/src/ParticleBuffer.ts | 15 +- .../src/ParticleContainer.ts | 29 +- .../src/ParticleRenderer.ts | 70 +- .../test/ParticleContainer.tests.ts | 11 +- .../test/ParticleRenderer.tests.ts | 35 +- packages/polyfill/README.md | 23 - packages/polyfill/package.json | 36 - packages/polyfill/src/Math.sign.ts | 17 - packages/polyfill/src/Number.isInteger.ts | 10 - packages/polyfill/src/Object.assign.ts | 10 - packages/polyfill/src/Promise.ts | 7 - packages/polyfill/src/globalThis.ts | 15 - packages/polyfill/src/index.ts | 36 - .../polyfill/src/requestAnimationFrame.ts | 79 - packages/prepare/README.md | 5 +- packages/prepare/global.d.ts | 7 + packages/prepare/package.json | 33 +- packages/prepare/src/BasePrepare.ts | 145 +- packages/prepare/src/CountLimiter.ts | 7 +- packages/prepare/src/Prepare.ts | 32 +- packages/prepare/src/TimeLimiter.ts | 5 +- packages/prepare/src/settings.ts | 3 +- packages/prepare/test/BasePrepare.tests.ts | 169 +- packages/prepare/test/CountLimiter.tests.ts | 21 +- packages/prepare/test/Prepare.tests.ts | 15 +- packages/prepare/test/TimeLimiter.tests.ts | 14 +- packages/runner/package.json | 19 +- packages/runner/src/Runner.ts | 11 +- packages/runner/test/Runner.tests.ts | 123 +- packages/settings/package.json | 21 +- packages/settings/src/adapter.ts | 41 + packages/settings/src/index.ts | 1 + packages/settings/src/settings.ts | 68 +- .../settings/src/utils/canUploadSameBuffer.ts | 3 +- packages/settings/src/utils/isMobile.ts | 42 +- .../src/utils/maxRecommendedTextures.ts | 3 +- packages/settings/test/settings.tests.ts | 64 +- packages/sprite-animated/package.json | 28 +- .../sprite-animated/src/AnimatedSprite.ts | 36 +- .../test/AnimatedSprite.tests.ts | 359 +- packages/sprite-tiling/README.md | 5 +- packages/sprite-tiling/package.json | 32 +- packages/sprite-tiling/src/TilingSprite.ts | 29 +- .../sprite-tiling/src/TilingSpriteRenderer.ts | 27 +- .../sprite-tiling/test/TilingSprite.tests.ts | 166 +- packages/sprite/package.json | 31 +- packages/sprite/src/Sprite.ts | 55 +- packages/sprite/test/Sprite.tests.ts | 133 +- packages/spritesheet/README.md | 4 +- packages/spritesheet/package.json | 29 +- packages/spritesheet/src/Spritesheet.ts | 115 +- packages/spritesheet/src/SpritesheetLoader.ts | 140 - packages/spritesheet/src/cacheSpritesheet.ts | 40 + packages/spritesheet/src/index.ts | 4 +- packages/spritesheet/src/loadSpritesheet.ts | 109 + .../spritesheet/src/resolveSpriteSheetUrl.ts | 32 + .../spritesheet/test/Spritesheet.tests.ts | 162 +- .../test/SpritesheetLoader.tests.ts | 442 +- packages/spritesheet/test/resources/atlas.crn | Bin 14681 -> 0 bytes .../spritesheet/test/resources/atlas_crn.json | 25 - .../test/resources/atlas_error.json | 17 - .../test/resources/multi-pack-0.json | 48 + .../test/resources/multi-pack-0.png | Bin 0 -> 2435 bytes .../test/resources/multi-pack-1.json | 23 + .../test/resources/multi-pack-1.png | Bin 0 -> 69086 bytes .../test/resources/spritesheet.json | 55 + .../test/resources/spritesheet.png | Bin 0 -> 3463 bytes packages/spritesheet/test/resources/test.json | 4 + packages/text-bitmap/README.md | 4 +- packages/text-bitmap/global.d.ts | 6 +- packages/text-bitmap/package.json | 37 +- packages/text-bitmap/src/BitmapFont.ts | 49 +- packages/text-bitmap/src/BitmapFontData.ts | 19 +- packages/text-bitmap/src/BitmapFontLoader.ts | 170 - packages/text-bitmap/src/BitmapText.ts | 94 +- packages/text-bitmap/src/BitmapTextStyle.ts | 6 +- .../text-bitmap/src/formats/TextFormat.ts | 12 +- packages/text-bitmap/src/formats/XMLFormat.ts | 7 +- .../src/formats/XMLStringFormat.ts | 11 +- packages/text-bitmap/src/formats/index.ts | 5 +- packages/text-bitmap/src/index.ts | 5 +- packages/text-bitmap/src/loadBitmapFont.ts | 66 + packages/text-bitmap/src/utils/drawGlyph.ts | 5 +- .../text-bitmap/src/utils/extractCharCode.ts | 1 + .../src/utils/generateFillStyle.ts | 16 +- .../src/utils/resolveCharacters.ts | 3 +- .../src/utils/splitTextToCharacters.ts | 1 + packages/text-bitmap/test/BitmapFont.tests.ts | 58 +- .../test/BitmapFontLoader.tests.ts | 851 +- packages/text-bitmap/test/BitmapText.tests.ts | 179 +- .../{bmtxt-test.png => bmGlyph-test.png} | Bin .../text-bitmap/test/resources/desyrel.png | Bin 0 -> 310362 bytes .../text-bitmap/test/resources/desyrel.xml | 1922 + packages/text/package.json | 30 +- packages/text/src/Text.ts | 103 +- packages/text/src/TextMetrics.ts | 178 +- packages/text/src/TextStyle.ts | 8 +- packages/text/src/const.ts | 5 +- packages/text/test/Text.tests.ts | 122 +- packages/text/test/TextMetrics.tests.ts | 467 +- packages/text/test/TextStyle.tests.ts | 39 +- packages/ticker/README.md | 4 +- packages/ticker/package.json | 24 +- packages/ticker/src/Ticker.ts | 44 +- packages/ticker/src/TickerListener.ts | 9 +- packages/ticker/src/TickerPlugin.ts | 19 +- packages/ticker/src/const.ts | 15 +- packages/ticker/src/settings.ts | 1 - packages/ticker/test/Ticker.tests.ts | 313 +- packages/ticker/test/TickerPlugin.tests.ts | 99 +- packages/unsafe-eval/README.md | 8 +- packages/unsafe-eval/package.json | 26 +- packages/unsafe-eval/src/install.ts | 3 +- packages/utils/package.json | 28 +- packages/utils/src/browser/hello.ts | 6 +- .../utils/src/browser/isWebGLSupported.ts | 9 +- packages/utils/src/color/hex.ts | 12 +- packages/utils/src/color/premultiply.ts | 11 +- packages/utils/src/const.ts | 1 - .../utils/src/data/createIndicesForQuads.ts | 5 +- packages/utils/src/data/getBufferType.ts | 4 +- .../utils/src/data/interleaveTypedArrays.ts | 2 +- packages/utils/src/data/pow2.ts | 9 +- packages/utils/src/data/removeItems.ts | 1 - packages/utils/src/data/sign.ts | 3 +- packages/utils/src/data/uid.ts | 3 +- packages/utils/src/index.ts | 28 +- packages/utils/src/logging/deprecation.ts | 1 - .../utils/src/media/CanvasRenderTarget.ts | 7 +- packages/utils/src/media/caches.ts | 11 +- packages/utils/src/media/trimCanvas.ts | 4 +- .../utils/src/network/decomposeDataUri.ts | 6 +- .../utils/src/network/determineCrossOrigin.ts | 7 +- .../utils/src/network/getResolutionOfUrl.ts | 7 +- packages/utils/src/path.ts | 681 + packages/utils/src/settings.ts | 2 - packages/utils/src/url.ts | 24 +- .../utils/test/CanvasRenderTarget.tests.ts | 41 +- packages/utils/test/TextureCache.tests.ts | 45 +- packages/utils/test/path.tests.ts | 316 + packages/utils/test/trimCanvas.tests.ts | 11 +- packages/utils/test/utils.tests.ts | 196 +- rollup.config.js | 135 +- scripts/fixPeerVersions.ts | 4 +- scripts/injectGlobalMixins.ts | 53 +- test/index.ts | 40 +- test/jest-global-setup.ts | 30 + test/jest-global-teardown.ts | 20 + test/packages.ts | 3 +- tools/integration-tests/package.json | 32 +- tools/integration-tests/test/Bounds.tests.ts | 267 +- .../integration-tests/test/Container.tests.ts | 82 +- .../test/DisplayObject.tests.ts | 13 +- .../test/getLocalBounds.tests.ts | 135 +- tsconfig.docs.json | 25 - tsconfig.json | 12 +- tsconfig.tests.json | 21 - webdoc.conf.json | 4 +- 743 files changed, 48255 insertions(+), 42185 deletions(-) delete mode 100644 .eslintrc.tests.json rename {packages/polyfill => bundles/pixi.js-node}/LICENSE (100%) create mode 100644 bundles/pixi.js-node/README.md create mode 100644 bundles/pixi.js-node/package.json create mode 100644 bundles/pixi.js-node/src/adapter/NodeCanvasElement.ts create mode 100644 bundles/pixi.js-node/src/adapter/NodeCanvasResource.ts create mode 100644 bundles/pixi.js-node/src/adapter/adapter.ts create mode 100644 bundles/pixi.js-node/src/adapter/index.ts create mode 100644 bundles/pixi.js-node/src/adapter/loadNodeBase64.ts create mode 100644 bundles/pixi.js-node/src/adapter/loadNodeBitmapFont.ts create mode 100644 bundles/pixi.js-node/src/adapter/loadNodeFont.ts create mode 100644 bundles/pixi.js-node/src/adapter/loadNodeTexture.ts create mode 100644 bundles/pixi.js-node/src/adapter/polyfills.ts create mode 100644 bundles/pixi.js-node/src/index.ts create mode 100644 jest.config.js create mode 100644 packages/assets/README.md create mode 100644 packages/assets/package.json create mode 100644 packages/assets/src/Assets.ts create mode 100644 packages/assets/src/BackgroundLoader.ts create mode 100644 packages/assets/src/cache/Cache.ts create mode 100644 packages/assets/src/cache/CacheParser.ts create mode 100644 packages/assets/src/cache/index.ts create mode 100644 packages/assets/src/cache/parsers/cacheTextureArray.ts create mode 100644 packages/assets/src/cache/parsers/index.ts create mode 100644 packages/assets/src/detections/index.ts create mode 100644 packages/assets/src/detections/parsers/detectAvif.ts create mode 100644 packages/assets/src/detections/parsers/detectDefaults.ts create mode 100644 packages/assets/src/detections/parsers/detectWebp.ts create mode 100644 packages/assets/src/detections/parsers/index.ts create mode 100644 packages/assets/src/detections/utils/detectUtils.ts create mode 100644 packages/assets/src/detections/utils/index.ts create mode 100644 packages/assets/src/index.ts create mode 100644 packages/assets/src/loader/Loader.ts create mode 100644 packages/assets/src/loader/index.ts create mode 100644 packages/assets/src/loader/parsers/LoaderParser.ts create mode 100644 packages/assets/src/loader/parsers/WorkerManager.ts create mode 100644 packages/assets/src/loader/parsers/index.ts create mode 100644 packages/assets/src/loader/parsers/loadJson.ts create mode 100644 packages/assets/src/loader/parsers/loadTxt.ts create mode 100644 packages/assets/src/loader/parsers/loadWebFont.ts create mode 100644 packages/assets/src/loader/parsers/textures/index.ts create mode 100644 packages/assets/src/loader/parsers/textures/loadSVG.ts create mode 100644 packages/assets/src/loader/parsers/textures/loadTexture.ts create mode 100644 packages/assets/src/loader/parsers/textures/utils/checkExtension.ts create mode 100644 packages/assets/src/loader/parsers/textures/utils/createTexture.ts create mode 100644 packages/assets/src/loader/parsers/textures/utils/index.ts create mode 100644 packages/assets/src/loader/types.ts create mode 100644 packages/assets/src/resolver/Resolver.ts create mode 100644 packages/assets/src/resolver/index.ts create mode 100644 packages/assets/src/resolver/parsers/index.ts create mode 100644 packages/assets/src/resolver/parsers/resolveTextureUrl.ts create mode 100644 packages/assets/src/resolver/types.ts create mode 100644 packages/assets/src/utils/convertToList.ts create mode 100644 packages/assets/src/utils/createStringVariations.ts create mode 100644 packages/assets/src/utils/index.ts create mode 100644 packages/assets/src/utils/isSingleItem.ts create mode 100644 packages/assets/test/assets.tests.ts create mode 100644 packages/assets/test/assets/fonts/outfit.woff2 create mode 100644 packages/assets/test/assets/json/asset-manifest-2.json create mode 100644 packages/assets/test/assets/json/asset-manifest.json create mode 100644 packages/assets/test/assets/json/test.json create mode 100644 packages/assets/test/assets/spritesheet/multi-pack-0.json create mode 100644 packages/assets/test/assets/spritesheet/multi-pack-0.png create mode 100644 packages/assets/test/assets/spritesheet/multi-pack-1.json create mode 100644 packages/assets/test/assets/spritesheet/multi-pack-1.png create mode 100644 packages/assets/test/assets/spritesheet/spritesheet.json create mode 100644 packages/assets/test/assets/spritesheet/spritesheet.png rename packages/{loaders/test/resources => assets/test/assets/svg}/logo.svg (100%) rename packages/{loaders/test/resources/bunny.png => assets/test/assets/textures/bunny-2.png} (100%) mode change 100644 => 100755 create mode 100755 packages/assets/test/assets/textures/bunny.png create mode 100644 packages/assets/test/assets/textures/bunny.webp create mode 100644 packages/assets/test/assets/textures/profile-abel@0.5x.jpg create mode 100644 packages/assets/test/assets/textures/profile-abel@0.5x.webp create mode 100644 packages/assets/test/assets/textures/profile-abel@2x.jpg create mode 100644 packages/assets/test/assets/textures/profile-abel@2x.webp create mode 100644 packages/assets/test/cache.tests.ts create mode 100644 packages/assets/test/loader.tests.ts create mode 100644 packages/assets/test/resolver.tests.ts create mode 100644 packages/assets/test/sampleManifest.ts create mode 100644 packages/assets/test/sampleManifests.ts create mode 100644 packages/assets/test/utils.tests.ts rename packages/basis/src/{BasisLoader.ts => loader/BasisParser.ts} (65%) create mode 100644 packages/basis/src/loader/detectBasis.ts create mode 100644 packages/basis/src/loader/index.ts create mode 100644 packages/basis/src/loader/loadBasis.ts create mode 100644 packages/basis/test/basis.tests.ts rename packages/{loaders => canvas-display}/LICENSE (100%) rename packages/{canvas => }/canvas-display/README.md (100%) create mode 100644 packages/canvas-display/global.d.ts rename packages/{canvas => }/canvas-display/package.json (56%) rename packages/{canvas => }/canvas-display/src/Container.ts (86%) rename packages/{canvas => }/canvas-display/src/DisplayObject.ts (85%) rename packages/{canvas => }/canvas-display/src/index.ts (100%) rename packages/{canvas/canvas-sprite => canvas-display}/test/.eslintrc.json (100%) create mode 100644 packages/canvas-display/test/Container.tests.ts rename packages/{interaction => canvas-extract}/LICENSE (100%) create mode 100644 packages/canvas-extract/README.md create mode 100644 packages/canvas-extract/global.d.ts rename packages/{canvas => }/canvas-extract/package.json (53%) rename packages/{canvas => }/canvas-extract/src/CanvasExtract.ts (61%) rename packages/{canvas => }/canvas-extract/src/index.ts (100%) create mode 100644 packages/canvas-extract/test/CanvasExtract.tests.ts rename packages/{filters/filter-noise => canvas-graphics}/LICENSE (100%) create mode 100644 packages/canvas-graphics/README.md create mode 100644 packages/canvas-graphics/global.d.ts rename packages/{canvas => }/canvas-graphics/package.json (51%) rename packages/{canvas => }/canvas-graphics/src/CanvasGraphicsRenderer.ts (95%) rename packages/{canvas => }/canvas-graphics/src/Graphics.ts (82%) rename packages/{canvas => }/canvas-graphics/src/index.ts (100%) rename packages/{canvas => }/canvas-graphics/src/utils/PolygonUtils.ts (75%) rename packages/{canvas/canvas-renderer => canvas-graphics}/test/.eslintrc.json (100%) rename packages/{canvas => }/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts (77%) rename packages/{canvas => }/canvas-graphics/test/PolygonUtils.tests.ts (51%) rename packages/{filters/filter-fxaa => canvas-mesh}/LICENSE (100%) create mode 100644 packages/canvas-mesh/README.md rename packages/{canvas => }/canvas-mesh/global.d.ts (80%) rename packages/{canvas => }/canvas-mesh/package.json (50%) rename packages/{canvas => }/canvas-mesh/src/CanvasMeshRenderer.ts (91%) rename packages/{canvas => }/canvas-mesh/src/Mesh.ts (99%) rename packages/{canvas => }/canvas-mesh/src/MeshMaterial.ts (99%) rename packages/{canvas => }/canvas-mesh/src/NineSlicePlane.ts (93%) rename packages/{canvas => }/canvas-mesh/src/SimpleMesh.ts (99%) rename packages/{canvas => }/canvas-mesh/src/SimpleRope.ts (99%) rename packages/{canvas => }/canvas-mesh/src/index.ts (100%) rename packages/{canvas => }/canvas-mesh/src/settings.ts (83%) rename packages/{canvas => }/canvas-mesh/test/.eslintrc.json (100%) rename packages/{canvas => }/canvas-mesh/test/NineSlicePlane.tests.ts (59%) rename packages/{filters/filter-displacement => canvas-particle-container}/LICENSE (100%) rename packages/{canvas => }/canvas-particle-container/README.md (100%) rename packages/{canvas => }/canvas-particle-container/package.json (54%) rename packages/{canvas => }/canvas-particle-container/src/ParticleContainer.ts (81%) rename packages/{canvas => }/canvas-particle-container/src/index.ts (100%) rename packages/{filters/filter-color-matrix => canvas-prepare}/LICENSE (100%) create mode 100644 packages/canvas-prepare/README.md create mode 100644 packages/canvas-prepare/global.d.ts rename packages/{canvas => }/canvas-prepare/package.json (53%) rename packages/{canvas => }/canvas-prepare/src/CanvasPrepare.ts (79%) rename packages/{canvas => }/canvas-prepare/src/index.ts (100%) rename packages/{filters/filter-blur => canvas-renderer}/LICENSE (100%) rename packages/{canvas => }/canvas-renderer/README.md (100%) rename packages/{canvas => }/canvas-renderer/global.d.ts (88%) rename packages/{canvas => }/canvas-renderer/package.json (56%) rename packages/{canvas => }/canvas-renderer/src/BaseTexture.ts (91%) create mode 100644 packages/canvas-renderer/src/CanvasContextSystem.ts rename packages/{canvas/canvas-renderer/src/utils/CanvasMaskManager.ts => canvas-renderer/src/CanvasMaskSystem.ts} (91%) create mode 100644 packages/canvas-renderer/src/CanvasObjectRendererSystem.ts create mode 100644 packages/canvas-renderer/src/CanvasRenderer.ts rename packages/{canvas => }/canvas-renderer/src/canvasUtils.ts (94%) rename packages/{canvas => }/canvas-renderer/src/index.ts (53%) rename packages/{canvas => }/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts (77%) rename packages/{canvas => }/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts (92%) rename packages/{canvas/canvas-graphics => canvas-renderer}/test/.eslintrc.json (100%) rename packages/{canvas => }/canvas-renderer/test/CanvasMaskManager.tests.ts (54%) rename packages/{canvas => }/canvas-renderer/test/CanvasRenderer.tests.ts (62%) rename packages/{filters/filter-alpha => canvas-sprite-tiling}/LICENSE (100%) rename packages/{canvas => }/canvas-sprite-tiling/README.md (100%) create mode 100644 packages/canvas-sprite-tiling/global.d.ts rename packages/{canvas => }/canvas-sprite-tiling/package.json (51%) rename packages/{canvas => }/canvas-sprite-tiling/src/TilingSprite.ts (93%) rename packages/{canvas => }/canvas-sprite-tiling/src/index.ts (100%) rename packages/{canvas/canvas-text => canvas-sprite}/LICENSE (100%) create mode 100644 packages/canvas-sprite/README.md create mode 100644 packages/canvas-sprite/global.d.ts rename packages/{canvas => }/canvas-sprite/package.json (52%) rename packages/{canvas => }/canvas-sprite/src/CanvasSpriteRenderer.ts (65%) rename packages/{canvas => }/canvas-sprite/src/Sprite.ts (70%) rename packages/{canvas => }/canvas-sprite/src/index.ts (100%) rename packages/{canvas/canvas-display => canvas-sprite}/test/.eslintrc.json (100%) create mode 100644 packages/canvas-sprite/test/CanvasSpriteRenderer.tests.ts rename packages/{canvas/canvas-sprite => canvas-text}/LICENSE (100%) rename packages/{canvas => }/canvas-text/README.md (100%) rename packages/{canvas => }/canvas-text/package.json (50%) rename packages/{canvas => }/canvas-text/src/Text.ts (99%) rename packages/{canvas => }/canvas-text/src/index.ts (100%) delete mode 100644 packages/canvas/canvas-display/LICENSE delete mode 100644 packages/canvas/canvas-display/global.d.ts delete mode 100644 packages/canvas/canvas-display/test/Container.tests.ts delete mode 100644 packages/canvas/canvas-extract/README.md delete mode 100644 packages/canvas/canvas-extract/test/CanvasExtract.tests.ts delete mode 100644 packages/canvas/canvas-graphics/README.md delete mode 100644 packages/canvas/canvas-graphics/global.d.ts delete mode 100644 packages/canvas/canvas-mesh/README.md delete mode 100644 packages/canvas/canvas-prepare/README.md delete mode 100644 packages/canvas/canvas-renderer/src/CanvasRenderer.ts delete mode 100644 packages/canvas/canvas-renderer/src/Renderer.ts delete mode 100644 packages/canvas/canvas-sprite-tiling/global.d.ts delete mode 100644 packages/canvas/canvas-sprite/README.md delete mode 100644 packages/canvas/canvas-sprite/global.d.ts delete mode 100644 packages/canvas/canvas-sprite/test/CanvasSpriteRenderer.tests.ts create mode 100644 packages/compressed-textures/global.d.ts delete mode 100644 packages/compressed-textures/src/loaders/CompressedTextureLoader.ts delete mode 100644 packages/compressed-textures/src/loaders/KTXLoader.ts create mode 100644 packages/compressed-textures/src/loaders/compressedTextureExtensions.ts create mode 100644 packages/compressed-textures/src/loaders/detectCompressedTextures.ts create mode 100644 packages/compressed-textures/src/loaders/loadDDS.ts create mode 100644 packages/compressed-textures/src/loaders/loadKTX.ts delete mode 100644 packages/compressed-textures/src/loaders/registerCompressedTextures.ts create mode 100644 packages/compressed-textures/src/loaders/resolveCompressedTextureUrl.ts create mode 100644 packages/compressed-textures/src/parsers/index.ts rename packages/compressed-textures/src/{loaders/DDSLoader.ts => parsers/parseDDS.ts} (51%) create mode 100644 packages/compressed-textures/src/parsers/parseKTX.ts create mode 100644 packages/compressed-textures/test/compressed-textures.tests.ts delete mode 100644 packages/core/src/AbstractRenderer.ts delete mode 100644 packages/core/src/IRenderableObject.ts create mode 100644 packages/core/src/IRenderer.ts delete mode 100644 packages/core/src/IRenderingContext.ts delete mode 100644 packages/core/src/ISystem.ts create mode 100644 packages/core/src/background/BackgroundSystem.ts delete mode 100644 packages/core/src/batch/BatchPluginFactory.ts rename packages/core/src/batch/{AbstractBatchRenderer.ts => BatchRenderer.ts} (89%) create mode 100644 packages/core/src/framebuffer/MultisampleSystem.ts create mode 100644 packages/core/src/plugin/PluginSystem.ts create mode 100644 packages/core/src/render/ObjectRendererSystem.ts create mode 100644 packages/core/src/renderTexture/GenerateTextureSystem.ts create mode 100644 packages/core/src/startup/StartupSystem.ts create mode 100644 packages/core/src/system/ISystem.ts create mode 100644 packages/core/src/system/SystemManager.ts create mode 100644 packages/core/src/view/ViewSystem.ts create mode 100644 packages/core/test/resources/cube-face.jpg rename packages/{canvas/canvas-extract => extensions}/LICENSE (94%) create mode 100644 packages/extensions/README.md create mode 100644 packages/extensions/package.json create mode 100644 packages/extensions/src/index.ts create mode 100644 packages/extensions/test/extensions.tests.ts create mode 100644 packages/extract/global.d.ts rename packages/{canvas/canvas-sprite-tiling => filter-alpha}/LICENSE (100%) rename packages/{filters => }/filter-alpha/README.md (100%) rename packages/{filters => }/filter-alpha/package.json (59%) rename packages/{filters => }/filter-alpha/src/AlphaFilter.ts (99%) rename packages/{filters => }/filter-alpha/src/alpha.frag (100%) rename packages/{filters => }/filter-alpha/src/index.ts (100%) create mode 100644 packages/filter-alpha/test/AlphaFilter.tests.ts rename packages/{canvas/canvas-renderer => filter-blur}/LICENSE (100%) rename packages/{filters => }/filter-blur/README.md (100%) rename packages/{filters => }/filter-blur/package.json (56%) rename packages/{filters => }/filter-blur/src/BlurFilter.ts (93%) rename packages/{filters => }/filter-blur/src/BlurFilterPass.ts (96%) rename packages/{filters => }/filter-blur/src/generateBlurFragSource.ts (98%) rename packages/{filters => }/filter-blur/src/generateBlurVertSource.ts (100%) rename packages/{filters => }/filter-blur/src/getMaxBlurKernelSize.ts (100%) rename packages/{filters => }/filter-blur/src/index.ts (100%) create mode 100644 packages/filter-blur/test/BlurFilter.tests.ts rename packages/{canvas/canvas-prepare => filter-color-matrix}/LICENSE (100%) rename packages/{filters => }/filter-color-matrix/README.md (100%) rename packages/{filters => }/filter-color-matrix/package.json (57%) rename packages/{filters => }/filter-color-matrix/src/ColorMatrixFilter.ts (97%) rename packages/{filters => }/filter-color-matrix/src/colorMatrix.frag (100%) rename packages/{filters => }/filter-color-matrix/src/index.ts (100%) rename packages/{filters => }/filter-color-matrix/test/ColorMatrixFilter.tests.ts (80%) rename packages/{canvas/canvas-particle-container => filter-displacement}/LICENSE (100%) rename packages/{filters => }/filter-displacement/README.md (100%) rename packages/{filters => }/filter-displacement/package.json (57%) rename packages/{filters => }/filter-displacement/src/DisplacementFilter.ts (93%) rename packages/{filters => }/filter-displacement/src/displacement.frag (100%) rename packages/{filters => }/filter-displacement/src/displacement.vert (100%) rename packages/{filters => }/filter-displacement/src/index.ts (100%) rename packages/{canvas/canvas-mesh => filter-fxaa}/LICENSE (100%) rename packages/{filters => }/filter-fxaa/README.md (100%) rename packages/{filters => }/filter-fxaa/package.json (56%) rename packages/{filters => }/filter-fxaa/src/FXAAFilter.ts (98%) rename packages/{filters => }/filter-fxaa/src/fxaa.frag (100%) rename packages/{filters => }/filter-fxaa/src/fxaa.vert (100%) rename packages/{filters => }/filter-fxaa/src/index.ts (100%) rename packages/{canvas/canvas-graphics => filter-noise}/LICENSE (100%) rename packages/{filters => }/filter-noise/README.md (100%) rename packages/{filters => }/filter-noise/package.json (57%) rename packages/{filters => }/filter-noise/src/NoiseFilter.ts (99%) rename packages/{filters => }/filter-noise/src/index.ts (100%) rename packages/{filters => }/filter-noise/src/noise.frag (100%) delete mode 100644 packages/filters/filter-alpha/test/AlphaFilter.tests.ts delete mode 100644 packages/filters/filter-blur/test/BlurFilter.tests.ts delete mode 100644 packages/interaction/README.md delete mode 100644 packages/interaction/global.d.ts delete mode 100644 packages/interaction/package.json delete mode 100644 packages/interaction/src/InteractionData.ts delete mode 100644 packages/interaction/src/InteractionEvent.ts delete mode 100644 packages/interaction/src/InteractionManager.ts delete mode 100644 packages/interaction/src/InteractionTrackingData.ts delete mode 100644 packages/interaction/src/TreeSearch.ts delete mode 100644 packages/interaction/src/index.ts delete mode 100644 packages/interaction/src/interactiveTarget.ts delete mode 100755 packages/interaction/test/InteractionData.tests.ts delete mode 100644 packages/interaction/test/InteractionManager.tests.ts delete mode 100644 packages/interaction/test/MockPointer.ts delete mode 100644 packages/loaders/README.md delete mode 100644 packages/loaders/global.d.ts delete mode 100644 packages/loaders/package.json delete mode 100644 packages/loaders/src/AppLoaderPlugin.ts delete mode 100644 packages/loaders/src/Loader.ts delete mode 100644 packages/loaders/src/LoaderResource.ts delete mode 100644 packages/loaders/src/TextureLoader.ts delete mode 100644 packages/loaders/src/base/AsyncQueue.ts delete mode 100644 packages/loaders/src/base/Signal.ts delete mode 100644 packages/loaders/src/base/encodeBinary.ts delete mode 100644 packages/loaders/src/base/parseUri.ts delete mode 100644 packages/loaders/src/index.ts delete mode 100644 packages/loaders/src/middleware/caching.ts delete mode 100644 packages/loaders/src/middleware/index.ts delete mode 100644 packages/loaders/src/middleware/parsing.ts delete mode 100644 packages/loaders/test/AppLoaderPlugin.tests.ts delete mode 100644 packages/loaders/test/AsyncQueue.tests.ts delete mode 100644 packages/loaders/test/Loader.tests.ts delete mode 100644 packages/loaders/test/LoaderBase.tests.ts delete mode 100644 packages/loaders/test/LoaderResource.test.ts delete mode 100644 packages/loaders/test/TextureLoader.tests.ts delete mode 100644 packages/loaders/test/fixtureData.ts delete mode 100644 packages/loaders/test/fixtures/data.ts delete mode 100644 packages/loaders/test/fixtures/spritesheet.ts delete mode 100644 packages/loaders/test/resources/data/hud.json delete mode 100644 packages/loaders/test/resources/data/hud.png delete mode 100644 packages/loaders/test/resources/data/hud2.json delete mode 100644 packages/loaders/test/resources/data/hud2.png delete mode 100644 packages/loaders/test/resources/index.ts delete mode 100644 packages/polyfill/README.md delete mode 100644 packages/polyfill/package.json delete mode 100644 packages/polyfill/src/Math.sign.ts delete mode 100644 packages/polyfill/src/Number.isInteger.ts delete mode 100644 packages/polyfill/src/Object.assign.ts delete mode 100644 packages/polyfill/src/Promise.ts delete mode 100644 packages/polyfill/src/globalThis.ts delete mode 100644 packages/polyfill/src/index.ts delete mode 100644 packages/polyfill/src/requestAnimationFrame.ts create mode 100644 packages/prepare/global.d.ts create mode 100644 packages/settings/src/adapter.ts delete mode 100644 packages/spritesheet/src/SpritesheetLoader.ts create mode 100644 packages/spritesheet/src/cacheSpritesheet.ts create mode 100644 packages/spritesheet/src/loadSpritesheet.ts create mode 100644 packages/spritesheet/src/resolveSpriteSheetUrl.ts delete mode 100644 packages/spritesheet/test/resources/atlas.crn delete mode 100644 packages/spritesheet/test/resources/atlas_crn.json delete mode 100644 packages/spritesheet/test/resources/atlas_error.json create mode 100644 packages/spritesheet/test/resources/multi-pack-0.json create mode 100644 packages/spritesheet/test/resources/multi-pack-0.png create mode 100644 packages/spritesheet/test/resources/multi-pack-1.json create mode 100644 packages/spritesheet/test/resources/multi-pack-1.png create mode 100644 packages/spritesheet/test/resources/spritesheet.json create mode 100644 packages/spritesheet/test/resources/spritesheet.png create mode 100644 packages/spritesheet/test/resources/test.json delete mode 100644 packages/text-bitmap/src/BitmapFontLoader.ts create mode 100644 packages/text-bitmap/src/loadBitmapFont.ts rename packages/text-bitmap/test/resources/{bmtxt-test.png => bmGlyph-test.png} (100%) create mode 100755 packages/text-bitmap/test/resources/desyrel.png create mode 100755 packages/text-bitmap/test/resources/desyrel.xml create mode 100644 packages/utils/src/path.ts create mode 100644 packages/utils/test/path.tests.ts create mode 100644 test/jest-global-setup.ts create mode 100644 test/jest-global-teardown.ts delete mode 100644 tsconfig.docs.json delete mode 100644 tsconfig.tests.json diff --git a/.eslintrc.json b/.eslintrc.json index 314daa40d86..a06a7eb4bed 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,9 +1,87 @@ { - "extends": [ - "@pixi/eslint-config" - ], - "rules": { - "@typescript-eslint/no-parameter-properties": 1, - "@typescript-eslint/type-annotation-spacing": 1 - } + "extends": ["@pixi/eslint-config"], + "plugins": ["jsdoc"], + "ignorePatterns": ["**/*.index.d.ts"], + "settings": { + "jsdoc": { + "mode": "typescript", + "tagNamePreference": { + "method": "method", + "function": "function", + "extends": "extends", + "typeParam": "typeParam", + "api": "api" + } + } + }, + "rules": { + "@typescript-eslint/consistent-type-imports": [1, { "disallowTypeAnnotations": false }], + "@typescript-eslint/no-parameter-properties": 1, + "@typescript-eslint/type-annotation-spacing": 1, + "jsdoc/multiline-blocks": [ + 1, + { "noMultilineBlocks": true, "minimumLengthForMultiline": 115 } + ], + "jsdoc/check-access": 1, + "jsdoc/check-alignment": 1, + "jsdoc/check-param-names": 1, + "jsdoc/check-property-names": 1, + "jsdoc/check-tag-names": 1, + "jsdoc/check-types": 1, + "jsdoc/check-values": 1, + "jsdoc/empty-tags": 1, + "jsdoc/implements-on-classes": 1, + "jsdoc/newline-after-description": [1, "never"], + "jsdoc/no-multi-asterisks": [1, { "allowWhitespace": true }], + "jsdoc/no-undefined-types": [ + "warn", + { + "definedTypes": [ + "PIXI", + "WEBGL_draw_buffers", + "WEBGL_depth_texture", + "OES_texture_float", + "WEBGL_lose_context", + "OES_vertex_array_object", + "EXT_texture_filter_anisotropic" + ] + } + ], + "jsdoc/require-param": 1, + "jsdoc/require-param-description": 0, + "jsdoc/require-param-name": 1, + "jsdoc/require-param-type": [ + "warn", + { "contexts": ["TSMethodSignature"] } + ], + "jsdoc/require-property": 1, + "jsdoc/require-property-description": 1, + "jsdoc/require-property-name": 1, + "jsdoc/require-property-type": 1, + "jsdoc/require-returns-description": 1, + "jsdoc/tag-lines": 1, + "jsdoc/valid-types": 1 + }, + "overrides": [ + { + "files": ["*.tests.ts", "*.test.ts"], + "globals": { + "expect": false, + "assert": false, + "sinon": false + }, + "rules": { + "@typescript-eslint/no-unused-expressions": 0, + "@typescript-eslint/dot-notation": [ + 0, + { + "allowPrivateClassPropertyAccess": true, + "allowProtectedClassPropertyAccess": true, + "allowIndexSignaturePropertyAccess": true + } + ], + "dot-notation": 0 + } + } + ] } diff --git a/.eslintrc.tests.json b/.eslintrc.tests.json deleted file mode 100644 index f3aff556872..00000000000 --- a/.eslintrc.tests.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "./.eslintrc.json", - "globals": { - "expect": false, - "assert": false, - "sinon": false - }, - "rules": { - "func-names": 0, - "no-unused-expressions": 0, - "@typescript-eslint/no-var-requires": 0, - "@typescript-eslint/no-unused-expressions": 0, - "@typescript-eslint/no-use-before-define": 0, - "@typescript-eslint/no-unused-vars": 0, - "@typescript-eslint/no-empty-function": 0 - } -} diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3677fcffee8..7de7a6ec4d6 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -64,11 +64,11 @@ bug if it ever happens again. This prevents regressions from sneaking in. Tips for a faster workflow: - Run `npm start` in one terminal. This watches the source tree and compiles it incrementally. -- When desired, run `npm run unit-test` in another terminal. This runs tests using the compilation output from `npm start`. -- Run `npm run unit-test:debug` to use headful DevTools to debug or develop tests -- For testing specific a package, use `--package` flag, e.g., `npm run unit-test -- --package=@pixi/math` -- The `--package` flag supports multiple packages, e.g., `npm run unit-test -- --package=@pixi/math --package=@pixi/core` -- The `--package` flag supports debug testing as well, e.g., `npm run unit-test:debug -- --package=@pixi/math` +- When desired, run `npm run test` in another terminal. This runs tests using the compilation output from `npm start`. +- Run `npm run test:debug` to use headful DevTools to debug or develop tests +- For testing specific a package, use `npm run test:pkg` with the `--packages` flag, e.g., `npm run test:pkg -- --packages=@pixi/math` +- The `--packages` flag supports multiple packages, e.g., `npm run test:pkg -- --packages=@pixi/math @pixi/core` +- Run `npm run test:pkg:debug` for debugging specific packages `npm run test:pkg:debug -- --packages=@pixi/math @pixi/core` ### Submitting Your Change diff --git a/.github/stale.yml b/.github/stale.yml index d3d2203e322..325fa49c3ad 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,8 +1,8 @@ # Number of days of inactivity before an issue becomes stale -daysUntilStale: 90 +daysUntilStale: 180 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 14 +daysUntilClose: 90 # Issues with these labels will never be considered stale #exemptLabels: diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 6361a741a0b..fde6667934c 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -25,7 +25,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v2 with: - node-version: 12 + node-version: 16 registry-url: 'https://registry.npmjs.org' - name: Install npm run: npm install -g npm@>=7 @@ -37,7 +37,7 @@ jobs: - name: Run Unit Tests uses: GabrielBB/xvfb-action@v1.0 with: - run: npm run coverage:ci + run: npm run coverage env: NODE_ENV: production diff --git a/.gitignore b/.gitignore index fd5f469803d..bf1b2f27915 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,8 @@ packages/**/index.d.ts .vscode pixi.code-workspace +# IntelliJ +*.iml + # webdoc api dist/docs/pixi.api.json diff --git a/.npmrc b/.npmrc index c42da845b44..120713954a8 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ engine-strict = true +legacy-peer-deps diff --git a/README.md b/README.md index ac1788d2d4b..5a664f35d68 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ PixiJS — The HTML5 Creation Engine ![pixi.js logo](https://pixijs.download/pixijs-banner-no-version.png) -[](https://join.slack.com/t/pixijs/shared_invite/zt-dcem1map-uVuVGC7pZ0trF8SrcA2p9g) +[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/QrnxmQUPGV) [![npm version](https://badge.fury.io/js/pixi.js.svg)](https://badge.fury.io/js/pixi.js) [![Node.js CI](https://github.com/pixijs/pixi.js/workflows/Node.js%20CI/badge.svg)](https://github.com/pixi.js/pixi.js/actions?query=workflow%3A%22Node.js+CI%22) @@ -25,15 +25,17 @@ as any breakthroughs will be posted up there too! ### What to Use PixiJS for and When to Use It -PixiJS is a rendering library that will allow you to create rich, interactive graphics, cross platform applications, and games without having to dive into the WebGL API or deal with browser and device compatibility. +PixiJS is a rendering library that will allow you to create rich, interactive graphics, cross-platform applications, and games without having to dive into the WebGL API or deal with browser and device compatibility. -PixiJS has full [WebGL](https://en.wikipedia.org/wiki/WebGL) support and seamlessly falls back to HTML5's [canvas](https://en.wikipedia.org/wiki/Canvas_element) if needed. As a framework, PixiJS is a fantastic tool for authoring interactive content, *especially with the move away from Adobe Flash in recent years*. Use it for your graphics rich, interactive websites, applications, and HTML5 games. Out of the box cross-platform compatibility and graceful degradation mean you have less work to do and have more fun doing it! If you want to create polished and refined experiences relatively quickly, without delving into dense, low level code, all while avoiding the headaches of browser inconsistencies, then sprinkle your next project with some PixiJS magic! +PixiJS has full [WebGL](https://en.wikipedia.org/wiki/WebGL) support and seamlessly falls back to HTML5's [canvas](https://en.wikipedia.org/wiki/Canvas_element) if needed. As a framework, PixiJS is a fantastic tool for authoring interactive content, *especially with the move away from Adobe Flash in recent years*. Use it for your graphics rich, interactive websites, applications, and HTML5 games. Out of the box, cross-platform compatibility and graceful degradation mean you have less work to do and have more fun doing it! If you want to create polished and refined experiences relatively quickly, without delving into dense, low-level code, all while avoiding the headaches of browser inconsistencies, then sprinkle your next project with some PixiJS magic! **Boost your development and feel free to use your imagination!** ### Learn ### - Website: Find out more about PixiJS on the [official website](https://www.pixijs.com/). -- Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). +- Getting started: + - Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). + - Also check out @miltoncandelero's PixiJS tutorials aimed toward videogames with recipes, best practices and TypeScript / npm / webpack setup [here](https://www.pixijselementals.com/) - Examples: Get stuck right in and play around with PixiJS code and features right [here](https://pixijs.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.io/docs/). - Guide: Supplementary guide to the API documentation [here](https://pixijs.io/guides/). @@ -42,8 +44,7 @@ PixiJS has full [WebGL](https://en.wikipedia.org/wiki/WebGL) support and seamles ### Community ### - Forums: Check out the [forum](https://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your PixiJS questions. - Inspiration: Check out the [gallery](https://www.pixijs.com/gallery) to see some of the amazing things people have created! -- Chat: You can join us on [Gitter](https://gitter.im/pixijs/pixi.js) To chat about PixiJS. We also now have a Slack channel. If you would like to join it please Send me an email (mat@goodboydigital.com) and I will invite you in. - +- Chat: You can join us on [Discord](https://discord.gg/QrnxmQUPGV) to chat about PixiJS. ### Setup ### @@ -174,6 +175,23 @@ Then, to build the source, run: npm run build ``` +#### Error installing gl package + +In most cases installing `gl` from npm should just work. However, if you run into problems you might need to adjust your system configuration and make sure all your dependencies are up to date + +Please refer to the [gl installation guide](https://www.npmjs.com/package/gl/v/4.5.3-win64.0#system-dependencies) for more information. + +#### Error installing canvas package + +The [canvas](https://www.npmjs.com/package/canvas) library currently being used does not have a pre-built version for every environment. +When the package detects an unsupported environment, it will try to build from source. + +To build from source you will need to make sure you have the following dependencies installed and then reinstall: + +`brew install pkg-config cairo pango libpng jpeg giflib librsvg` + +For non-mac users, please refer to the [canvas installation guide](https://www.npmjs.com/package/canvas#compiling) for more information. + ### How to generate the documentation ### The docs can be generated using npm: @@ -187,5 +205,3 @@ The documentation uses [webdoc](https://github.com/webdoc-labs/webdoc) in combin ### License ### This content is released under the (http://opensource.org/licenses/MIT) MIT License. - -[![Analytics](https://ga-beacon.appspot.com/UA-39213431-2/pixi.js/index)](https://github.com/igrigorik/ga-beacon) diff --git a/bundles/pixi.js-legacy/README.md b/bundles/pixi.js-legacy/README.md index 6b31ef7e0f0..4cd511938d4 100644 --- a/bundles/pixi.js-legacy/README.md +++ b/bundles/pixi.js-legacy/README.md @@ -7,13 +7,21 @@ The aim of this project is to provide a fast lightweight 2D library that works across all devices. The PixiJS renderer allows everyone to enjoy the power of hardware acceleration without prior knowledge of WebGL. Also, it's fast. Really fast. -**Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** +**We are now a part of the [Open Collective](https://opencollective.com/pixijs) and with your support you can help us make PixiJS even better. To make a donation, simply click the button below and we'll love you forever!** + +
+ +
This package is the same as **pixi.js**, but provides fallback support for browsers that do not support WebGL or more modern JavaScript features. ### Setup -PixiJS can be installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) to integration with [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/), [Rollup](https://rollupjs.org/), [Electron](https://electron.atom.io/), [NW.js](https://nwjs.io/) or other module backed environments. +PixiJS can be installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) to integrate with [Webpack](https://webpack.js.org/)](https://webpack.js.org/), [Browserify](http://browserify.org/), [Rollup](https://rollupjs.org/), [Electron](https://electron.atom.io/), [NW.js](https://nwjs.io/) or other module backed environments. #### Install @@ -65,5 +73,3 @@ app.loader.add('bunny', 'bunny.png').load((loader, resources) => { ### License This content is released under the (http://opensource.org/licenses/MIT) MIT License. - -[![Analytics](https://ga-beacon.appspot.com/UA-39213431-2/pixi.js/index)](https://github.com/igrigorik/ga-beacon) diff --git a/bundles/pixi.js-legacy/package.json b/bundles/pixi.js-legacy/package.json index 78f208fcaf5..871f277b893 100644 --- a/bundles/pixi.js-legacy/package.json +++ b/bundles/pixi.js-legacy/package.json @@ -1,6 +1,6 @@ { "name": "pixi.js-legacy", - "version": "6.3.0", + "version": "7.0.0-alpha", "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ @@ -11,12 +11,25 @@ ], "standalone": true, "main": "dist/cjs/pixi-legacy.js", - "module": "dist/esm/pixi-legacy.js", + "module": "dist/esm/pixi-legacy.mjs", "bundle": "dist/browser/pixi-legacy.js", "bundleModule": "dist/browser/pixi-legacy.mjs", "bundleOutput": { "name": "PIXI" }, + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/pixi-legacy.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/pixi-legacy.js" + } + } + }, "homepage": "http://www.pixijs.com/", "bugs": "https://github.com/pixijs/pixi.js/issues", "license": "MIT", @@ -25,7 +38,6 @@ "url": "https://github.com/pixijs/pixi.js.git" }, "files": [ - "lib/", "dist/", "*.d.ts" ], @@ -34,16 +46,16 @@ "url": "https://opencollective.com/pixijs" }, "dependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-extract": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-particle-container": "6.3.0", - "@pixi/canvas-prepare": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-sprite-tiling": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "pixi.js": "6.3.0" + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-extract": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-particle-container": "7.0.0-alpha", + "@pixi/canvas-prepare": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-sprite-tiling": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "pixi.js": "7.0.0-alpha" } } diff --git a/bundles/pixi.js-legacy/src/index.ts b/bundles/pixi.js-legacy/src/index.ts index 3da0fb39338..bb22bc7b0d0 100644 --- a/bundles/pixi.js-legacy/src/index.ts +++ b/bundles/pixi.js-legacy/src/index.ts @@ -1,32 +1,12 @@ -import { AccessibilityManager, InteractionManager } from 'pixi.js'; -import { CanvasRenderer, canvasUtils } from '@pixi/canvas-renderer'; -import { CanvasMeshRenderer } from '@pixi/canvas-mesh'; -import { CanvasGraphicsRenderer } from '@pixi/canvas-graphics'; -import { CanvasSpriteRenderer } from '@pixi/canvas-sprite'; -import { CanvasExtract } from '@pixi/canvas-extract'; -import { CanvasPrepare } from '@pixi/canvas-prepare'; import '@pixi/canvas-sprite-tiling'; import '@pixi/canvas-particle-container'; import '@pixi/canvas-display'; import '@pixi/canvas-text'; -CanvasRenderer.registerPlugin('accessibility', AccessibilityManager); -CanvasRenderer.registerPlugin('extract', CanvasExtract); -CanvasRenderer.registerPlugin('graphics', CanvasGraphicsRenderer); -CanvasRenderer.registerPlugin('interaction', InteractionManager); -CanvasRenderer.registerPlugin('mesh', CanvasMeshRenderer); -CanvasRenderer.registerPlugin('prepare', CanvasPrepare); -CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer); - -// Export ES for those importing specifically by name, -// e.g., `import {autoDetectRenderer} from 'pixi.js-legacy'` export * from 'pixi.js'; -export { - CanvasRenderer, - CanvasGraphicsRenderer, - CanvasMeshRenderer, - CanvasSpriteRenderer, - CanvasExtract, - CanvasPrepare, - canvasUtils, -}; +export * from '@pixi/canvas-renderer'; +export * from '@pixi/canvas-mesh'; +export * from '@pixi/canvas-graphics'; +export * from '@pixi/canvas-sprite'; +export * from '@pixi/canvas-extract'; +export * from '@pixi/canvas-prepare'; diff --git a/packages/polyfill/LICENSE b/bundles/pixi.js-node/LICENSE similarity index 100% rename from packages/polyfill/LICENSE rename to bundles/pixi.js-node/LICENSE diff --git a/bundles/pixi.js-node/README.md b/bundles/pixi.js-node/README.md new file mode 100644 index 00000000000..5dea837c466 --- /dev/null +++ b/bundles/pixi.js-node/README.md @@ -0,0 +1,93 @@ +# @pixi/node + +**We are now a part of the [Open Collective](https://opencollective.com/pixijs) and with your support you can help us make PixiJS even better. To make a donation, simply click the button below and we'll love you forever!** + + + +## Setup + +### Install + +``` +npm install @pixi/node +``` + +There is no default export. The correct way to import PixiJS is: + +```js +import * as PIXI from "@pixi/node"; +``` + +#### Error installing gl package + +In most cases installing `gl` from npm should just work. However, if you run into problems you might need to adjust your system configuration and make sure all your dependencies are up to date + +Please refer to the [gl installation guide](https://www.npmjs.com/package/gl/v/4.5.3-win64.0#system-dependencies) for more information. + +### Error installing canvas package + +The [canvas](https://www.npmjs.com/package/canvas) library currently being used does not have a pre-built version for every environment. +When the package detects an unsupported environment, it will try to build from source. + +To build from source you will need to make sure you have the following dependencies installed and then reinstall: + +`brew install pkg-config cairo pango libpng jpeg giflib librsvg` + +For non-mac users, please refer to the [canvas installation guide](https://www.npmjs.com/package/canvas#compiling) for more information. + +## Basic Usage Example + +```js +import { Application, Sprite, Assets } from '@pixi/node'; +import path from 'path'; +import { writeFileSync } from 'fs'; + +// This package requires the new asset loader to be used. +// Initialize the new assets loader +await Assets.init(); + +// The application will create a renderer using WebGL. It will also setup the ticker +// and the root stage Container. +const app = new Application(); + +// load a sprite +const bunnyTexture = await Assets.load(path.join(process.cwd(), 'assets/bunny.png')); +// create sprite from texture +const bunny = Sprite.from(bunnyTexture); + +// Setup the position of the bunny +bunny.x = app.renderer.width / 2; +bunny.y = app.renderer.height / 2; + +// Rotate around the center +bunny.anchor.x = 0.5; +bunny.anchor.y = 0.5; + +// Add the bunny to the scene we are building. +app.stage.addChild(bunny); + +// Listen for frame updates +app.ticker.add(() => { + // each frame we spin the bunny around a bit + bunny.rotation += 0.01; +}); + +// extract and save the stage +app.renderer.render(app.stage); +const base64Image = app.renderer.plugins.extract + .canvas(app.stage) + .toDataURL('image/png'); + +const base64Data = base64Image.replace(/^data:image\/png;base64,/, ''); +const output = `./test.png`; + +writeFileSync(output, base64Data, 'base64'); +``` + +### License + +This content is released under the (http://opensource.org/licenses/MIT) MIT License. diff --git a/bundles/pixi.js-node/package.json b/bundles/pixi.js-node/package.json new file mode 100644 index 00000000000..1f98a41351f --- /dev/null +++ b/bundles/pixi.js-node/package.json @@ -0,0 +1,76 @@ +{ + "name": "@pixi/node", + "version": "7.0.0-alpha", + "description": "Bundle for PixiJS with support for NodeJS", + "homepage": "http://pixijs.com/", + "bugs": "https://github.com/pixijs/pixi.js/issues", + "repository": { + "type": "git", + "url": "https://github.com/pixijs/pixi.js.git" + }, + "license": "MIT", + "author": "PixiJS Team", + "main": "dist/cjs/node.cjs", + "module": "dist/esm/node.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/node.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/node.cjs" + } + } + }, + "files": [ + "dist", + "*.d.ts" + ], + "engines": { + "node": ">=16" + }, + "dependencies": { + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha", + "@types/gl": "^4.1.0", + "@types/xml2js": "^0.4.11", + "canvas": "^2.9.1", + "cross-fetch": "^3.1.5", + "gl": "^5.0.0", + "xml2js": "^0.4.23" + }, + "nodeDependencies": [ + "fs", + "path" + ], + "publishConfig": { + "access": "public" + } +} diff --git a/bundles/pixi.js-node/src/adapter/NodeCanvasElement.ts b/bundles/pixi.js-node/src/adapter/NodeCanvasElement.ts new file mode 100644 index 00000000000..8fccaa43a92 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/NodeCanvasElement.ts @@ -0,0 +1,318 @@ +/* eslint-disable dot-notation */ +/* eslint-disable func-names */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment + +import type { JpegConfig, NodeCanvasRenderingContext2DSettings, PdfConfig, PngConfig } from 'canvas'; +import { Canvas, CanvasRenderingContext2D, Image } from 'canvas'; +import { EventEmitter } from '@pixi/utils'; +import createGLContext from 'gl'; +import type { ContextIds } from '@pixi/settings'; + +function putImageData(gl: WebGLRenderingContext, canvas: NodeCanvasElement) +{ + const { width, height } = canvas; + + const ctx = canvas['_ctx'] as CanvasRenderingContext2D; + + const data = ctx.getImageData(0, 0, width, height); + + const pixels = new Uint8Array(width * height * 4); + + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + for (let i = 0; i < height; i++) + { + for (let j = 0; j < width; j++) + { + const col = j; + const row = height - i - 1; + + for (let k = 0; k < 4; k++) + { + const idx = (4 * ((row * width) + col)) + k; + const idx2 = (4 * ((i * width) + col)) + k; + + data.data[idx] = pixels[idx2]; + } + } + } + + ctx.putImageData(data, 0, 0); + + return ctx; +} + +type TempCtx = WebGLRenderingContext & { + canvas: NodeCanvasElement +}; + +/** + * A node implementation of a canvas element. + * Uses node-canvas and gl packages to provide the same + * functionality as a normal HTMLCanvasElement. + * @class + * @memberof PIXI + */ +export class NodeCanvasElement extends Canvas +{ + public style: Record; + private _gl: WebGLRenderingContext; + private _event: EventEmitter; + private _contextType: ContextIds; + private _ctx: CanvasRenderingContext2D | WebGLRenderingContext; + + constructor(width = 1, height = 1, type?: 'image' | 'pdf' | 'svg') + { + super(width, height, type); + this._event = new EventEmitter(); + this.style = {}; + } + + // @ts-expect-error - overriding width to be a getter/setter + get width() + { + return super['width']; + } + + set width(value) + { + if (this._gl) + { + const ext = this._gl.getExtension('STACKGL_resize_drawingbuffer'); + + ext.resize(value, this.height); + } + super['width'] = value; + } + + // @ts-expect-error - overriding height to be a getter/setter + get height() + { + return super['height']; + } + + set height(value) + { + if (this._gl) + { + const ext = this._gl.getExtension('STACKGL_resize_drawingbuffer'); + + ext.resize(this.width, value); + } + super['height'] = value; + } + + get clientWidth() + { + return super['width']; + } + + get clientHeight() + { + return super['height']; + } + + /** + * Internal method to update the context before drawing. + * @private + */ + public _updateCtx() + { + const gl = this._gl; + + if (gl) + { + putImageData(gl, this); + } + + return this._ctx; + } + + // @ts-expect-error - overriding getContext + override getContext( + type: ContextIds, + options?: NodeCanvasRenderingContext2DSettings | WebGLContextAttributes + ): CanvasRenderingContext2D | WebGLRenderingContext + { + if (type === 'webgl2') return undefined; + if (this._contextType && this._contextType !== type) return null; + if (this._gl) return this._gl; + this._contextType = type; + if (type === 'experimental-webgl' || type === 'webgl') + { + const { width, height } = this; + + this._ctx = super.getContext('2d', options as NodeCanvasRenderingContext2DSettings); + const ctx = createGLContext(width, height, options as WebGLContextAttributes) as TempCtx; + const _getUniformLocation = ctx.getUniformLocation; + + type Program = WebGLProgram & {_uniforms: any[]}; + // Temporary fix https://github.com/stackgl/headless-gl/issues/170 + ctx.getUniformLocation = function (program: Program, name) + { + if (program._uniforms && !(/\[\d+\]$/).test(name)) + { + const reg = new RegExp(`${name}\\[\\d+\\]$`); + + for (let i = 0; i < program._uniforms.length; i++) + { + const _name = program._uniforms[i].name; + + if (reg.test(_name)) + { + name = _name; + } + } + } + + return _getUniformLocation.call(this, program, name); + }; + + (ctx as any).canvas = this as NodeCanvasElement; + const _texImage2D = ctx.texImage2D; + + ctx.texImage2D = function (...args: any) + { + let pixels = args[args.length - 1]; + + if (pixels && pixels._image) pixels = pixels._image; + if (pixels instanceof Image) + { + const canvas = new Canvas(pixels.width, pixels.height); + + canvas.getContext('2d').drawImage(pixels, 0, 0); + args[args.length - 1] = canvas; + } + + return _texImage2D.apply(this, args); + }; + this._gl = ctx; + + return this._gl; + } + + return super.getContext(type, options as NodeCanvasRenderingContext2DSettings); + } + + /** + * For image canvases, encodes the canvas as a PNG. For PDF canvases, + * encodes the canvas as a PDF. For SVG canvases, encodes the canvas as an + * SVG. + */ + toBuffer(cb: (err: Error | null, result: Buffer) => void): void; + toBuffer(cb: (err: Error | null, result: Buffer) => void, mimeType: 'image/png', config?: PngConfig): void; + toBuffer(cb: (err: Error | null, result: Buffer) => void, mimeType: 'image/jpeg', config?: JpegConfig): void; + /** + * For image canvases, encodes the canvas as a PNG. For PDF canvases, + * encodes the canvas as a PDF. For SVG canvases, encodes the canvas as an + * SVG. + */ + toBuffer(): Buffer; + toBuffer(mimeType: 'image/png', config?: PngConfig): Buffer; + toBuffer(mimeType: 'image/jpeg', config?: JpegConfig): Buffer; + toBuffer(mimeType: 'application/pdf', config?: PdfConfig): Buffer; + /** + * Returns the unencoded pixel data, top-to-bottom. On little-endian (most) + * systems, the array will be ordered BGRA; on big-endian systems, it will + * be ARGB. + */ + toBuffer(mimeType: 'raw'): Buffer; + /** + * Returns a buffer of the canvas contents. + * @param args - the arguments to pass to the toBuffer method + */ + public toBuffer(...args: any): Buffer + { + const gl = this._gl; + + if (gl) + { + putImageData(gl, this); + } + + // @ts-expect-error - overriding toBuffer + return super.toBuffer(...args); + } + + /** Defaults to PNG image. */ + toDataURL(): string; + toDataURL(mimeType: 'image/png'): string; + toDataURL(mimeType: 'image/jpeg', quality?: number): string; + /** _Non-standard._ Defaults to PNG image. */ + toDataURL(cb: (err: Error | null, result: string) => void): void; + /** _Non-standard._ */ + toDataURL(mimeType: 'image/png', cb: (err: Error | null, result: string) => void): void; + /** _Non-standard._ */ + toDataURL(mimeType: 'image/jpeg', cb: (err: Error | null, result: string) => void): void; + /** _Non-standard._ */ + toDataURL(mimeType: 'image/jpeg', config: JpegConfig, cb: (err: Error | null, result: string) => void): void; + /** _Non-standard._ */ + toDataURL(mimeType: 'image/jpeg', quality: number, cb: (err: Error | null, result: string) => void): void; + /** + * Returns a base64 encoded string representation of the canvas. + * @param args - The arguments to pass to the toDataURL method. + */ + public toDataURL(...args: any): string + { + const gl = this._gl; + + if (gl) + { + putImageData(gl, this); + } + + // @ts-expect-error - overriding toDataURL + return super.toDataURL(...args); + } + + /** + * Adds the listener for the specified event. + * @param type - The type of event to listen for. + * @param listener - The callback to invoke when the event is fired. + */ + addEventListener(type: string, listener: (...args: any[]) => void) + { + return this._event.addListener(type, listener); + } + + /** + * Removes the listener for the specified event. + * @param type - The type of event to listen for. + * @param listener - The callback to invoke when the event is fired. + */ + removeEventListener(type: string, listener: (...args: any[]) => void) + { + if (listener) + { + return this._event.removeListener(type, listener); + } + + return this._event.removeAllListeners(type); + } + + /** + * Dispatches the specified event. + * @param event - The event to emit. + * @param event.type - The type of event. + */ + dispatchEvent(event: {type: string, [key: string]: any}) + { + event.target = this; + + return this._event.emit(event.type, event); + } +} + +const _drawImage = CanvasRenderingContext2D.prototype.drawImage; + +// We hack the drawImage method to make it work with our custom Canvas, ensuring that the context is updated before we draw +// eslint-disable-next-line func-names +CanvasRenderingContext2D.prototype.drawImage = function (img: Canvas, ...args: any) +{ + const _img = img as NodeCanvasElement; + + // call ctx to sync image data + if (img instanceof Canvas && _img['_gl']) _img._updateCtx(); + + return _drawImage.call(this, img, ...args); +}; diff --git a/bundles/pixi.js-node/src/adapter/NodeCanvasResource.ts b/bundles/pixi.js-node/src/adapter/NodeCanvasResource.ts new file mode 100644 index 00000000000..0814c3fee19 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/NodeCanvasResource.ts @@ -0,0 +1,118 @@ +import { ALPHA_MODES } from '@pixi/constants'; +import type { BaseTexture, GLTexture, Renderer } from '@pixi/core'; +import { Resource } from '@pixi/core'; +import { determineCrossOrigin } from '@pixi/utils'; + +import { NodeCanvasElement } from './NodeCanvasElement'; + +/** + * A canvas resource using node-canvas + * used for images, svg, and bitmap text + * @memberof PIXI + */ +export class NodeCanvasResource extends Resource +{ + /** + * The source element. + * @member {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|SVGElement} + * @readonly + */ + public source: NodeCanvasElement; + + /** + * If set to `true`, will force `texImage2D` over `texSubImage2D` for uploading. + * Certain types of media (e.g. video) using `texImage2D` is more performant. + * @default false + * @private + */ + public noSubImage: boolean; + + constructor(source: NodeCanvasElement) + { + const sourceAny = source as any; + const width = sourceAny.naturalWidth || sourceAny.videoWidth || sourceAny.width; + const height = sourceAny.naturalHeight || sourceAny.videoHeight || sourceAny.height; + + super(width, height); + + this.source = source; + this.noSubImage = false; + } + + override upload(renderer: Renderer, baseTexture: BaseTexture, glTexture: GLTexture, source?: HTMLCanvasElement): boolean + { + const gl = renderer.gl; + const width = baseTexture.realWidth; + const height = baseTexture.realHeight; + + source = (source || this.source) as unknown as HTMLCanvasElement; + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, baseTexture.alphaMode === ALPHA_MODES.UNPACK); + + if (!this.noSubImage + && baseTexture.target === gl.TEXTURE_2D + && glTexture.width === width + && glTexture.height === height) + { + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, baseTexture.format, glTexture.type, source); + } + else + { + glTexture.width = width; + glTexture.height = height; + + gl.texImage2D(baseTexture.target, 0, glTexture.internalFormat, baseTexture.format, glTexture.type, source); + } + + return true; + } + + /** + * Checks if source width/height was changed, resize can cause extra baseTexture update. + * Triggers one update in any case. + */ + update(): void + { + if (this.destroyed) + { + return; + } + + const source = this.source as any; + + const width = source.naturalWidth || source.videoWidth || source.width; + const height = source.naturalHeight || source.videoHeight || source.height; + + this.resize(width, height); + + super.update(); + } + + dispose(): void + { + this.source = null; + } + + static override test(source: unknown): source is NodeCanvasElement + { + return source instanceof NodeCanvasElement; + } + + /** + * Set cross origin based detecting the url and the crossorigin + * @param element - Element to apply crossOrigin + * @param url - URL to check + * @param crossorigin - Cross origin value to use + */ + static crossOrigin(element: HTMLImageElement | HTMLVideoElement, url: string, crossorigin?: boolean | string): void + { + if (crossorigin === undefined && url.indexOf('data:') !== 0) + { + element.crossOrigin = determineCrossOrigin(url); + } + else if (crossorigin !== false) + { + element.crossOrigin = typeof crossorigin === 'string' ? crossorigin : 'anonymous'; + } + } +} diff --git a/bundles/pixi.js-node/src/adapter/adapter.ts b/bundles/pixi.js-node/src/adapter/adapter.ts new file mode 100644 index 00000000000..4e3f5d9eba1 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/adapter.ts @@ -0,0 +1,61 @@ +import type { IAdapter } from '@pixi/settings'; +import { settings } from '@pixi/settings'; +import { fetch, Request, Response } from 'cross-fetch'; +import createContext from 'gl'; +import { NodeCanvasElement } from './NodeCanvasElement'; + +import fs from 'fs'; +import { path } from '@pixi/utils'; + +export const NodeAdapter = { + /** + * Creates a canvas element of the given size. + * This canvas is created using the node-canvas package and uses the gl package to create a webgl context. + * @param width - width of the canvas + * @param height - height of the canvas + */ + createCanvas: (width?: number, height?: number) => new NodeCanvasElement(width, height) as unknown as HTMLCanvasElement, + /** Returns a webgl rendering context using the gl package. */ + getWebGLRenderingContext: () => createContext(1, 1) as unknown as typeof WebGLRenderingContext, + /** Returns the fake user agent string of `node` */ + getNavigator: () => ({ userAgent: 'node' }), + /** Returns the path from which the process is being run */ + getBaseUrl: () => process.cwd(), + fetch: (url: RequestInfo, options?: RequestInit) => + { + const request = new Request(url, options); + + // check if urls starts with http(s) as only these are supported by node-fetch + if (path.isUrl(request.url)) + { + return fetch(url, request); + } + + return new Promise((resolve, reject) => + { + const filePath = path.normalize(request.url); + + if (!fs.existsSync(filePath)) + { + reject(`File not found: ${filePath}`); + } + const readStream = fs.createReadStream(filePath); + + // eslint-disable-next-line func-names + readStream.on('open', function () + { + resolve(new Response(readStream as unknown as ReadableStream, { + url: request.url, + status: 200, + statusText: 'OK', + size: fs.statSync(filePath).size, + timeout: (request as any).timeout + } as unknown as ResponseInit)); + }); + }); + }, +} as IAdapter; + +settings.ADAPTER = NodeAdapter; + +export { settings }; diff --git a/bundles/pixi.js-node/src/adapter/index.ts b/bundles/pixi.js-node/src/adapter/index.ts new file mode 100644 index 00000000000..233773f5838 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/index.ts @@ -0,0 +1,9 @@ +import './polyfills'; + +export * from './NodeCanvasElement'; +export * from './NodeCanvasResource'; +export * from './loadNodeBitmapFont'; +export * from './loadNodeFont'; +export * from './loadNodeTexture'; +export * from './loadNodeBase64'; +export * from './adapter'; diff --git a/bundles/pixi.js-node/src/adapter/loadNodeBase64.ts b/bundles/pixi.js-node/src/adapter/loadNodeBase64.ts new file mode 100644 index 00000000000..b83c0711aca --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/loadNodeBase64.ts @@ -0,0 +1,51 @@ +import type { LoadAsset, LoaderParser } from '@pixi/assets'; +import { extensions, ExtensionType, Texture } from '@pixi/core'; +import { getResolutionOfUrl } from '@pixi/utils'; +import type { CanvasRenderingContext2D } from 'canvas'; +import { loadImage } from 'canvas'; +import { NodeCanvasElement } from './NodeCanvasElement'; + +const validMimes = ['image/png', 'image/jpg', 'image/jpeg', 'image/svg']; + +function isSupportedDataURL(url: string): boolean +{ + const match = url.match(/^data:([^;]+);base64,/); + + if (!match) return false; + + const mimeType = match[1]; + + return validMimes.includes(mimeType); +} + +/** loads our textures into a node canvas */ +export const loadNodeBase64 = { + extension: ExtensionType.LoadParser, + + test(url: string): boolean + { + return isSupportedDataURL(url); + }, + + async load(url: string, asset: LoadAsset): Promise + { + const image = await loadImage(url); + const canvas = new NodeCanvasElement(image.width, image.height); + const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; + + ctx.drawImage(image, 0, 0); + const texture = Texture.from(canvas as unknown as HTMLCanvasElement, { + resolution: getResolutionOfUrl(url), + ...asset.data + }); + + return texture; + }, + + unload(texture: Texture): void + { + texture.destroy(true); + } +} as LoaderParser; + +extensions.add(loadNodeBase64); diff --git a/bundles/pixi.js-node/src/adapter/loadNodeBitmapFont.ts b/bundles/pixi.js-node/src/adapter/loadNodeBitmapFont.ts new file mode 100644 index 00000000000..dfc91b2f81b --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/loadNodeBitmapFont.ts @@ -0,0 +1,198 @@ +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; +import type { Texture } from '@pixi/core'; +import { extensions, ExtensionType } from '@pixi/core'; +import { settings } from '@pixi/settings'; +import type { IBitmapFontRawData } from '@pixi/text-bitmap'; +import { BitmapFont, BitmapFontData, TextFormat, XMLStringFormat } from '@pixi/text-bitmap'; +import { path } from '@pixi/utils'; +import { parseStringPromise } from 'xml2js'; + +interface XMLRawJson +{ + font: { + info: Array<{$: IBitmapFontRawData['info'][0]}>, + common: Array<{$: IBitmapFontRawData['common'][0]}>, + pages: Array<{page: [{ $: IBitmapFontRawData['page'][0]}]}> + chars: Array<{$: {count: number}, char: [{ $: IBitmapFontRawData['char'][0]}]}> + kernings?: Array<{$: {count: number}, kerning: [{ $: IBitmapFontRawData['kerning'][0]}]}> + distanceField?: Array<{$: IBitmapFontRawData['distanceField'][0]}>, + } +} + +/** + * Parses a xml json into a BitmapFontData object. + * @param xml - The xml data to parse. + */ +function xmlJsonParser(xml: XMLRawJson) +{ + const data = new BitmapFontData(); + const font = xml.font; + const info = font.info; + const common = font.common; + const pages = font.pages; + const chars = font.chars; + const kernings = font.kernings; + const distanceField = font.distanceField; + + info.forEach((element) => + { + data.info.push({ + face: element.$.face, + size: parseInt(element.$.size, 10), + }); + }); + + common.forEach((element) => + { + data.common.push({ + lineHeight: parseInt(element.$.lineHeight, 10) + }); + }); + + pages.forEach((element) => + { + element.page.forEach((page) => + { + data.page.push({ + id: parseInt(page.$.id, 10), + file: page.$.file, + }); + }); + }); + + chars.forEach((info) => + { + const charArr = info.char; + + charArr.forEach((char) => + { + data.char.push({ + id: parseInt(char.$.id, 10), + page: parseInt(char.$.page, 10), + x: parseInt(char.$.x, 10), + y: parseInt(char.$.y, 10), + width: parseInt(char.$.width, 10), + height: parseInt(char.$.height, 10), + xoffset: parseInt(char.$.xoffset, 10), + yoffset: parseInt(char.$.yoffset, 10), + xadvance: parseInt(char.$.xadvance, 10), + }); + }); + }); + + kernings?.forEach((info) => + { + info.kerning?.forEach((kerning) => + data.kerning.push({ + first: parseInt(kerning.$.first, 10), + second: parseInt(kerning.$.second, 10), + amount: parseInt(kerning.$.amount, 10), + }) + ); + }); + + distanceField?.forEach((df) => + { + data.distanceField.push({ + distanceRange: parseInt(df.$.distanceRange, 10), + fieldType: df.$.fieldType, + }); + }); + + return data; +} + +/** + * Does the actual loading of the bitmap font data. + * @param src - The url of the font file. + * @param data - The bitmap font data for the file. + * @param loader - The loader instance. + */ +async function _loadBitmap(src: string, data: BitmapFontData, loader: Loader) +{ + const pages = data.page; + + const textureUrls = []; + + for (let i = 0; i < pages.length; ++i) + { + const pageFile = pages[i].file; + const url = path.join(path.dirname(src), pageFile); + + textureUrls.push(url); + } + + const loadedTextures = await loader.load(textureUrls) as Record; + const textures = textureUrls.map((url) => loadedTextures[url]); + + return BitmapFont.install(data, textures, true); +} + +/** + * Checks if the given string is an xml string. + * Performs the same check as the XMLStringFormat/XMLFormat class. + * @param data - the string data to test. + */ +async function xmlStringFormatTest(data: string): Promise +{ + if (typeof data === 'string' && data.indexOf('') > -1) + { + const xml = xmlJsonParser(await parseStringPromise(data)); + + return xml.page.length > 0 && xml.info[0].face !== null; + } + + return false; +} + +const validExtensions = ['.xml', '.fnt']; + +/** simple loader plugin for loading in bitmap fonts! */ +export const loadNodeBitmapFont = { + extension: ExtensionType.LoadParser, + + test(url: string): boolean + { + return validExtensions.includes(path.extname(url)); + }, + + async testParse(data: string): Promise + { + const isText = TextFormat.test(data); + const isXMLText = await xmlStringFormatTest(data); + + return isText || isXMLText; + }, + + async parse(asset: string, data: LoadAsset, loader: Loader): Promise + { + const isText = TextFormat.test(asset); + + if (isText) + { + const parsed = TextFormat.parse(asset); + + return await _loadBitmap(data.src, parsed, loader); + } + + return await _loadBitmap(data.src, XMLStringFormat.parse(asset), loader); + }, + + async load(url: string, _asset: LoadAsset, loader: Loader): Promise + { + const response = await settings.ADAPTER.fetch(url); + + const text = await response.text(); + + const data = xmlJsonParser(await parseStringPromise(text)); + + return await _loadBitmap(url, data, loader); + }, + + unload(bitmapFont: BitmapFont): void + { + bitmapFont.destroy(); + } +} as LoaderParser; + +extensions.add(loadNodeBitmapFont); diff --git a/bundles/pixi.js-node/src/adapter/loadNodeFont.ts b/bundles/pixi.js-node/src/adapter/loadNodeFont.ts new file mode 100644 index 00000000000..a70df10e228 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/loadNodeFont.ts @@ -0,0 +1,40 @@ +import type { LoadAsset, LoaderParser, LoadFontData } from '@pixi/assets'; +import { getFontFamilyName } from '@pixi/assets'; +import { extensions, ExtensionType } from '@pixi/core'; +import { registerFont } from 'canvas'; +import { path } from '@pixi/utils'; + +const validWeights = [ + 'normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900', +]; +const validFonts = ['.woff', '.woff2', '.ttf', '.otf']; + +/** loads a font from a file */ +export const loadNodeFont = { + extension: ExtensionType.LoadParser, + + test(url: string): boolean + { + return validFonts.includes(path.extname(url)); + }, + + async load(url: string, options: LoadAsset): Promise + { + const name = options.data?.family ?? getFontFamilyName(url); + const weights = options.data?.weights?.filter((weight) => validWeights.includes(weight)) ?? ['normal']; + const data = options.data ?? {} as LoadFontData; + + for (let i = 0; i < weights.length; i++) + { + const weight = weights[i]; + + registerFont(url, { + ...data, + family: options.data?.family ?? name, + weight, + }); + } + }, +} as LoaderParser; + +extensions.add(loadNodeFont); diff --git a/bundles/pixi.js-node/src/adapter/loadNodeTexture.ts b/bundles/pixi.js-node/src/adapter/loadNodeTexture.ts new file mode 100644 index 00000000000..ad90b7c7267 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/loadNodeTexture.ts @@ -0,0 +1,54 @@ +import type { LoadAsset, LoaderParser } from '@pixi/assets'; +import { extensions, ExtensionType, Texture } from '@pixi/core'; +import { settings } from '@pixi/settings'; +import { getResolutionOfUrl, path } from '@pixi/utils'; +import type { CanvasRenderingContext2D } from 'canvas'; +import { loadImage } from 'canvas'; +import { NodeCanvasElement } from './NodeCanvasElement'; + +const validImages = ['.jpg', '.png', '.jpeg', '.svg']; +const validMimes = ['image/png', 'image/jpg', 'image/jpeg', 'image/svg']; + +function isSupportedDataURL(url: string): boolean +{ + const match = url.match(/^data:([^;]+);base64,/); + + if (!match) return false; + + const mimeType = match[1]; + + return validMimes.includes(mimeType); +} + +/** loads our textures into a node canvas */ +export const loadNodeTexture = { + extension: ExtensionType.LoadParser, + + test(url: string): boolean + { + return validImages.includes(path.extname(url)) || isSupportedDataURL(url); + }, + + async load(url: string, asset: LoadAsset): Promise + { + const data = await settings.ADAPTER.fetch(url); + const image = await loadImage(Buffer.from(await data.arrayBuffer())); + const canvas = new NodeCanvasElement(image.width, image.height); + const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; + + ctx.drawImage(image, 0, 0); + const texture = Texture.from(canvas as unknown as HTMLCanvasElement, { + resolution: getResolutionOfUrl(url), + ...asset.data + }); + + return texture; + }, + + unload(texture: Texture): void + { + texture.destroy(true); + } +} as LoaderParser; + +extensions.add(loadNodeTexture); diff --git a/bundles/pixi.js-node/src/adapter/polyfills.ts b/bundles/pixi.js-node/src/adapter/polyfills.ts new file mode 100644 index 00000000000..e3bc847b977 --- /dev/null +++ b/bundles/pixi.js-node/src/adapter/polyfills.ts @@ -0,0 +1,9 @@ +globalThis.requestAnimationFrame = function requestAnimationFrame(fn) +{ + return setTimeout(fn, 1000 / 60); +}; + +globalThis.cancelAnimationFrame = function cancelAnimationFrame(fn) +{ + return clearTimeout(fn); +}; diff --git a/bundles/pixi.js-node/src/index.ts b/bundles/pixi.js-node/src/index.ts new file mode 100644 index 00000000000..d6ec60c0d58 --- /dev/null +++ b/bundles/pixi.js-node/src/index.ts @@ -0,0 +1,59 @@ +import './adapter'; + +import { extensions, INSTALLED } from '@pixi/core'; +import { AlphaFilter } from '@pixi/filter-alpha'; +import { BlurFilter, BlurFilterPass } from '@pixi/filter-blur'; +import { ColorMatrixFilter } from '@pixi/filter-color-matrix'; +import { DisplacementFilter } from '@pixi/filter-displacement'; +import { FXAAFilter } from '@pixi/filter-fxaa'; +import { NoiseFilter } from '@pixi/filter-noise'; +import '@pixi/mixin-cache-as-bitmap'; +import '@pixi/mixin-get-child-by-name'; +import '@pixi/mixin-get-global-position'; +// eslint-disable-next-line @typescript-eslint/no-duplicate-imports +import { NodeCanvasResource } from './adapter'; +import { loadTextures, loadWebFont } from '@pixi/assets'; +import { ResizePlugin } from '@pixi/app'; +import { loadBitmapFont } from '@pixi/text-bitmap'; + +// Remove the default loader plugins +extensions.remove( + loadTextures, + loadWebFont, + loadBitmapFont, + ResizePlugin +); + +// reset installed resources and remove resize plugin from Application +INSTALLED.length = 0; +INSTALLED.push(NodeCanvasResource); + +export const filters = { + AlphaFilter, + BlurFilter, + BlurFilterPass, + ColorMatrixFilter, + DisplacementFilter, + FXAAFilter, + NoiseFilter, +}; + +// Export ES for those importing specifically by name, +export * from '@pixi/app'; +export * from './adapter'; +export * from '@pixi/assets'; +export * from '@pixi/core'; +export * from '@pixi/display'; +export * from '@pixi/extract'; +export * from '@pixi/graphics'; +export * from '@pixi/mesh'; +export * from '@pixi/mesh-extras'; +export * from '@pixi/particle-container'; +export * from '@pixi/prepare'; +export * from '@pixi/sprite'; +export * from '@pixi/sprite-animated'; +export * from '@pixi/sprite-tiling'; +export * from '@pixi/spritesheet'; +export * from '@pixi/text'; +export * from '@pixi/text-bitmap'; + diff --git a/bundles/pixi.js/README.md b/bundles/pixi.js/README.md index 656366fdad5..a031179c6f0 100644 --- a/bundles/pixi.js/README.md +++ b/bundles/pixi.js/README.md @@ -7,11 +7,17 @@ The aim of this project is to provide a fast lightweight 2D library that works across all devices. The PixiJS renderer allows everyone to enjoy the power of hardware acceleration without prior knowledge of WebGL. Also, it's fast. Really fast. -**Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** +**We are now a part of the [Open Collective](https://opencollective.com/pixijs) and with your support you can help us make PixiJS even better. To make a donation, simply click the button below and we'll love you forever!** + + ### Setup -PixiJS can be installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) to integration with [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/), [Rollup](https://rollupjs.org/), [Electron](https://electron.atom.io/), [NW.js](https://nwjs.io/) or other module backed environments. +PixiJS can be installed with [npm](https://docs.npmjs.com/getting-started/what-is-npm) to integrate with [Webpack](https://webpack.js.org/)](https://webpack.js.org/), [Browserify](http://browserify.org/), [Rollup](https://rollupjs.org/), [Electron](https://electron.atom.io/), [NW.js](https://nwjs.io/) or other module backed environments. #### Install @@ -63,5 +69,3 @@ app.loader.add('bunny', 'bunny.png').load((loader, resources) => { ### License This content is released under the (http://opensource.org/licenses/MIT) MIT License. - -[![Analytics](https://ga-beacon.appspot.com/UA-39213431-2/pixi.js/index)](https://github.com/igrigorik/ga-beacon) diff --git a/bundles/pixi.js/package.json b/bundles/pixi.js/package.json index 0c3a25c31a9..50c39544521 100644 --- a/bundles/pixi.js/package.json +++ b/bundles/pixi.js/package.json @@ -1,6 +1,6 @@ { "name": "pixi.js", - "version": "6.3.0", + "version": "7.0.0-alpha", "description": "PixiJS without the CanvasRenderer fallback, modern browsers only", "author": "Mat Groves", "contributors": [ @@ -11,12 +11,25 @@ ], "standalone": true, "main": "dist/cjs/pixi.js", - "module": "dist/esm/pixi.js", + "module": "dist/esm/pixi.mjs", "bundle": "dist/browser/pixi.js", "bundleModule": "dist/browser/pixi.mjs", "bundleOutput": { "name": "PIXI" }, + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/pixi.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/pixi.js" + } + } + }, "homepage": "http://www.pixijs.com/", "bugs": "https://github.com/pixijs/pixi.js/issues", "license": "MIT", @@ -28,7 +41,6 @@ "test": "floss --path test" }, "files": [ - "lib/", "dist/", "*.d.ts" ], @@ -37,40 +49,34 @@ "url": "https://opencollective.com/pixijs" }, "dependencies": { - "@pixi/accessibility": "6.3.0", - "@pixi/app": "6.3.0", - "@pixi/compressed-textures": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/extract": "6.3.0", - "@pixi/filter-alpha": "6.3.0", - "@pixi/filter-blur": "6.3.0", - "@pixi/filter-color-matrix": "6.3.0", - "@pixi/filter-displacement": "6.3.0", - "@pixi/filter-fxaa": "6.3.0", - "@pixi/filter-noise": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/interaction": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/mixin-cache-as-bitmap": "6.3.0", - "@pixi/mixin-get-child-by-name": "6.3.0", - "@pixi/mixin-get-global-position": "6.3.0", - "@pixi/particle-container": "6.3.0", - "@pixi/polyfill": "6.3.0", - "@pixi/prepare": "6.3.0", - "@pixi/runner": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/sprite-animated": "6.3.0", - "@pixi/sprite-tiling": "6.3.0", - "@pixi/spritesheet": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/text-bitmap": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" + "@pixi/accessibility": "7.0.0-alpha", + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/compressed-textures": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/events": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha" } } diff --git a/bundles/pixi.js/src/index.ts b/bundles/pixi.js/src/index.ts index 924e2eb13ec..27dd3060b86 100644 --- a/bundles/pixi.js/src/index.ts +++ b/bundles/pixi.js/src/index.ts @@ -1,19 +1,3 @@ -import '@pixi/polyfill'; - -import * as utils from '@pixi/utils'; -import { AccessibilityManager } from '@pixi/accessibility'; -import { InteractionManager } from '@pixi/interaction'; -import { Application } from '@pixi/app'; -import { Renderer, BatchRenderer } from '@pixi/core'; -import { Extract } from '@pixi/extract'; -import { Loader, AppLoaderPlugin } from '@pixi/loaders'; -import { CompressedTextureLoader, DDSLoader, KTXLoader } from '@pixi/compressed-textures'; -import { ParticleRenderer } from '@pixi/particle-container'; -import { Prepare } from '@pixi/prepare'; -import { SpritesheetLoader } from '@pixi/spritesheet'; -import { TilingSpriteRenderer } from '@pixi/sprite-tiling'; -import { BitmapFontLoader } from '@pixi/text-bitmap'; -import { TickerPlugin } from '@pixi/ticker'; import { AlphaFilter } from '@pixi/filter-alpha'; import { BlurFilter, BlurFilterPass } from '@pixi/filter-blur'; import { ColorMatrixFilter } from '@pixi/filter-color-matrix'; @@ -24,41 +8,6 @@ import '@pixi/mixin-cache-as-bitmap'; import '@pixi/mixin-get-child-by-name'; import '@pixi/mixin-get-global-position'; -// Install renderer plugins -Renderer.registerPlugin('accessibility', AccessibilityManager); -Renderer.registerPlugin('extract', Extract); -Renderer.registerPlugin('interaction', InteractionManager); -Renderer.registerPlugin('particle', ParticleRenderer); -Renderer.registerPlugin('prepare', Prepare); -Renderer.registerPlugin('batch', BatchRenderer); -Renderer.registerPlugin('tilingSprite', TilingSpriteRenderer); - -// Install loader plugins -Loader.registerPlugin(BitmapFontLoader); -Loader.registerPlugin(CompressedTextureLoader); -Loader.registerPlugin(DDSLoader); -Loader.registerPlugin(KTXLoader); -Loader.registerPlugin(SpritesheetLoader); - -// Install application plugins -Application.registerPlugin(TickerPlugin); -Application.registerPlugin(AppLoaderPlugin); - -/** - * String of the current PIXI version. - * - * @static - * @constant - * @memberof PIXI - * @name VERSION - * @type {string} - */ -export const VERSION = '$_VERSION'; - -/** - * @namespace PIXI - */ - /** * This namespace contains WebGL-only display filters that can be applied * to DisplayObjects using the {@link PIXI.DisplayObject#filters filters} property. @@ -68,7 +17,6 @@ export const VERSION = '$_VERSION'; * PixiJS Filters repository. * * All filters must extend {@link PIXI.Filter}. - * * @example * // Create a new application * const app = new PIXI.Application(); @@ -99,26 +47,20 @@ export const filters = { // Export ES for those importing specifically by name, export * from '@pixi/accessibility'; export * from '@pixi/app'; -export * from '@pixi/constants'; +export * from '@pixi/assets'; export * from '@pixi/compressed-textures'; export * from '@pixi/core'; export * from '@pixi/display'; +export * from '@pixi/events'; export * from '@pixi/extract'; export * from '@pixi/graphics'; -export * from '@pixi/loaders'; -export * from '@pixi/interaction'; -export * from '@pixi/math'; export * from '@pixi/mesh'; export * from '@pixi/mesh-extras'; export * from '@pixi/particle-container'; export * from '@pixi/prepare'; -export * from '@pixi/runner'; export * from '@pixi/sprite'; export * from '@pixi/spritesheet'; export * from '@pixi/sprite-animated'; export * from '@pixi/sprite-tiling'; export * from '@pixi/text'; export * from '@pixi/text-bitmap'; -export * from '@pixi/ticker'; -export * from '@pixi/settings'; -export { utils }; diff --git a/global.d.ts b/global.d.ts index 5cbf29eafc3..ab1af6122aa 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line spaced-comment +/// + declare module '*.frag' { const value: string; @@ -9,5 +12,3 @@ declare module '*.vert' { export default value; } - -declare module 'es6-promise-polyfill' diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000000..45449689be8 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,34 @@ +module.exports = { + testPathIgnorePatterns: ['/node_modules/', '/src/', '/dist/', '/lib/', '/out/'], + preset: 'ts-jest/presets/js-with-ts', + runner: 'jest-electron/runner', + testEnvironment: 'jest-electron/environment', + setupFilesAfterEnv: [ + 'jest-extended/all', + ], + globalSetup: '/test/jest-global-setup.ts', + globalTeardown: '/test/jest-global-teardown.ts', + transform: { + '\\.vert$': 'jest-raw-loader', + '\\.frag$': 'jest-raw-loader', + }, + moduleNameMapper: { + '^@pixi/(.*)$': '/packages/$1/src', + }, + testMatch: ['**/?(*.)+(spec|tests).[tj]s?(x)'], + globals: { + 'ts-jest': { + tsconfig: { + module: 'ESNext', + esModuleInterop: true, + }, + diagnostics: false, + }, + }, + collectCoverageFrom: [ + '/packages/**/*.ts', + '!/packages/**/*.d.ts', + '!/packages/polyfill/**/*.ts', + ], + coverageDirectory: '/dist/coverage', +}; diff --git a/lerna.json b/lerna.json index 94542e18c76..ce2c23e3660 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { "lerna": "4.0.0", "useWorkspaces": true, - "version": "6.3.0" + "version": "7.0.0-alpha" } diff --git a/package-lock.json b/package-lock.json index cec841b9dc5..965224a958f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,94 +8,87 @@ "workspaces": [ "bundles/*", "packages/*", - "packages/canvas/*", - "packages/filters/*", "tools/*" ], "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@microsoft/api-extractor": "^7.9.11", - "@pixi-build-tools/api-extractor-lerna-monorepo": "^1.0.3", - "@pixi/eslint-config": "^2.0.1", + "@microsoft/api-extractor": "~7.20.1", + "@pixi-build-tools/api-extractor-lerna-monorepo": "~1.1.0", + "@pixi/eslint-config": "^4.0.1", "@pixi/webdoc-template": "^1.5.3", "@rollup/plugin-alias": "^3.1.1", - "@rollup/plugin-buble": "^0.21.3", "@rollup/plugin-commonjs": "^15.1.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^9.0.0", - "@rollup/plugin-typescript": "^6.0.0", - "@types/mocha": "^8.2.3", - "@webdoc/cli": "^1.5.5", - "chai": "~4.3.6", + "@types/css-font-loading-module": "^0.0.7", + "@types/jest": "^26.0.0", + "@webdoc/cli": "^2.0.0", "copyfiles": "^2.1.0", "cross-env": "^5.2.0", "electron": "^12.0.0", + "esbuild": "^0.14.48", "eslint": "^7.2.0", - "floss": "^5.0.0", + "eslint-plugin-jsdoc": "^39.2.9", "glob": "^7.1.3", + "http-server": "^14.1.1", + "jest": "^26.0.0", + "jest-electron": "^0.1.12", + "jest-extended": "^1.2.1", + "jest-raw-loader": "^1.0.1", "lerna": "^4.0.0", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", "pre-commit": "^1.2.2", "rimraf": "^2.6.3", - "rollup": "^2.70.1", + "rollup": "^2.75.7", + "rollup-plugin-esbuild": "^4.9.1", "rollup-plugin-jscc": "^2.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "rollup-plugin-string": "^3.0.0", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-typescript": "^1.0.1", - "sinon": "^7.3.2", - "sinon-chai": "^3.3.0", + "ts-jest": "^26.0.0", "ts-node": "^9.0.0", "tsconfig-paths": "^3.10.1", - "typescript": "^3.9.5", - "workspaces-run": "^1.0.1" + "typescript": "~4.3.0", + "workspaces-run": "^1.0.1", + "yargs-parser": "^21.0.1" }, "engines": { - "node": ">=12", + "node": ">=14", "npm": ">=7", "yarn": "please-use-npm" } }, "bundles/pixi.js": { - "version": "6.3.0", - "license": "MIT", - "dependencies": { - "@pixi/accessibility": "6.3.0", - "@pixi/app": "6.3.0", - "@pixi/compressed-textures": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/extract": "6.3.0", - "@pixi/filter-alpha": "6.3.0", - "@pixi/filter-blur": "6.3.0", - "@pixi/filter-color-matrix": "6.3.0", - "@pixi/filter-displacement": "6.3.0", - "@pixi/filter-fxaa": "6.3.0", - "@pixi/filter-noise": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/interaction": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/mixin-cache-as-bitmap": "6.3.0", - "@pixi/mixin-get-child-by-name": "6.3.0", - "@pixi/mixin-get-global-position": "6.3.0", - "@pixi/particle-container": "6.3.0", - "@pixi/polyfill": "6.3.0", - "@pixi/prepare": "6.3.0", - "@pixi/runner": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/sprite-animated": "6.3.0", - "@pixi/sprite-tiling": "6.3.0", - "@pixi/spritesheet": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/text-bitmap": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" + "version": "7.0.0-alpha", + "license": "MIT", + "dependencies": { + "@pixi/accessibility": "7.0.0-alpha", + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/compressed-textures": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/events": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha" }, "funding": { "type": "opencollective", @@ -103,59 +96,136 @@ } }, "bundles/pixi.js-legacy": { - "version": "6.3.0", + "version": "7.0.0-alpha", "license": "MIT", "dependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-extract": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-particle-container": "6.3.0", - "@pixi/canvas-prepare": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-sprite-tiling": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "pixi.js": "6.3.0" + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-extract": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-particle-container": "7.0.0-alpha", + "@pixi/canvas-prepare": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-sprite-tiling": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "pixi.js": "7.0.0-alpha" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/pixijs" } }, + "bundles/pixi.js-node": { + "name": "@pixi/node", + "version": "7.0.0-alpha", + "license": "MIT", + "dependencies": { + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha", + "@types/gl": "^4.1.0", + "@types/xml2js": "^0.4.11", + "canvas": "^2.9.1", + "cross-fetch": "^3.1.5", + "gl": "^5.0.0", + "xml2js": "^0.4.23" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { - "version": "7.12.13", + "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, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.12.13" + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.14.0", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=6.9.0" + } }, "node_modules/@babel/core": { - "version": "7.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helpers": "^7.14.0", - "@babel/parser": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0", + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "json5": "^2.2.1", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -166,24 +236,31 @@ } }, "node_modules/@babel/core/node_modules/@babel/traverse": { - "version": "7.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -198,8 +275,9 @@ }, "node_modules/@babel/core/node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", @@ -209,22 +287,18 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/core/node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/generator": { - "version": "7.14.1", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", + "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.14.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.18.9", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/generator/node_modules/jsesc": { @@ -238,120 +312,169 @@ "node": ">=4" } }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz", - "integrity": "sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.13.16", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.13.15", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.14.5", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", "semver": "^6.3.0" }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", + "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-function-name": { - "version": "7.12.13", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.12.13", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.13.12", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.13.12" + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "dependencies": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-simple-access": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms/node_modules/@babel/traverse": { - "version": "7.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -366,56 +489,73 @@ }, "node_modules/@babel/helper-module-transforms/node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.12.13", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.13.12", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.12" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers/node_modules/@babel/traverse": { - "version": "7.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -430,72 +570,92 @@ }, "node_modules/@babel/helper-replace-supers/node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/@babel/helper-simple-access": { - "version": "7.13.12", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.13.12" + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.12.13", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.12.13" + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helpers/node_modules/@babel/traverse": { - "version": "7.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/helpers/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -510,23 +670,29 @@ }, "node_modules/@babel/helpers/node_modules/ms": { "version": "2.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/@babel/highlight": { - "version": "7.14.0", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.14.0", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.14.1", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", + "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -534,10 +700,188 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", + "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", + "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "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": { "@babel/helper-plugin-utils": "^7.14.5" @@ -549,13 +893,30 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-flow-comments": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-comments/-/plugin-transform-flow-comments-7.17.12.tgz", + "integrity": "sha512-H0hZkvKuOmBGN12CqqiiqB7uNGoYUagi8RBdR2KUuAGwGRMfM7IheYPraSX9CHQXDbSriR6QWBq0lQ9d5AKXVw==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-flow": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", - "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -565,16 +926,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", - "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz", + "integrity": "sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.9" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -584,12 +945,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz", - "integrity": "sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", "dev": true, "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.14.5" + "@babel/plugin-transform-react-jsx": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -599,13 +960,13 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz", - "integrity": "sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -615,17 +976,17 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.14.5.tgz", - "integrity": "sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-react-display-name": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.5", - "@babel/plugin-transform-react-jsx-development": "^7.14.5", - "@babel/plugin-transform-react-pure-annotations": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -643,20 +1004,23 @@ } }, "node_modules/@babel/template": { - "version": "7.12.13", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/generator": "^7.9.5", @@ -671,9 +1035,8 @@ }, "node_modules/@babel/traverse/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -688,28 +1051,48 @@ }, "node_modules/@babel/traverse/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", + "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "node_modules/@changesets/types": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/types/-/types-0.4.0.tgz", - "integrity": "sha512-TclHHKDVYQ8rJGZgVeWiF7c91yWzTTWdPagltgutelGu/Psup5PQlUq6svx7S8suj+jXcaE34yEEsfIvzXXB2Q==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "dev": true, + "dependencies": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } }, "node_modules/@electron/get": { "version": "1.12.4", @@ -748,6 +1131,19 @@ } } }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/@electron/get/node_modules/ms": { "version": "2.1.2", "dev": true, @@ -761,17 +1157,39 @@ "semver": "bin/semver.js" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.29.0", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.3.1", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "~3.0.1" + }, + "engines": { + "node": "^14 || ^16 || ^17 || ^18" + } + }, + "node_modules/@fork-of/git-branch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fork-of/git-branch/-/git-branch-2.1.1.tgz", + "integrity": "sha512-X4dAtlXMGKYzOsc6W9LhKZh2m8L4KgWr6Im4gOTAhw7Mqekw8PWSGb8cetO3SVejp5gDbv0iMpd24vsks6S2TA==", + "dev": true, + "dependencies": { + "find-git-root": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@gar/promisify": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", - "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", - "dev": true + "license": "MIT" }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=6.9.0" } @@ -803,298 +1221,403 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/nyc-config-typescript": { - "version": "1.0.1", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2" - }, + "license": "MIT", "engines": { "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" }, - "peerDependencies": { - "nyc": ">=15", - "source-map-support": "*", - "ts-node": "*" + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jsbits/escape-regex-str": { - "version": "1.0.3", + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=4.2" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jsbits/get-package-version": { - "version": "1.0.3", + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4.2" + "node": ">=7.0.0" } }, - "node_modules/@lerna/add": { + "node_modules/@jest/console/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/add/-/add-4.0.0.tgz", - "integrity": "sha512-cpmAH1iS3k8JBxNvnMqrGTTjbY/ZAiKa1ChJzFevMYY3eeqbvhsBKnBcxjRXtdrJ6bd3dCQM+ZtK+0i682Fhng==", + "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/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@lerna/bootstrap": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "npm-package-arg": "^8.1.0", - "p-map": "^4.0.0", - "pacote": "^11.2.6", - "semver": "^7.3.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/add/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "node_modules/@jest/core": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", + "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==", "dev": true, "dependencies": { - "npmlog": "^4.1.2" + "@jest/console": "^26.6.2", + "@jest/reporters": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^26.6.2", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-resolve-dependencies": "^26.6.3", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "jest-watcher": "^26.6.2", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/add/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/@jest/core/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/@jest/core/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": { - "lru-cache": "^6.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/add/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/core/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": { - "yallist": "^4.0.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/add/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/@jest/core/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": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/add/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/@jest/core/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": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/@lerna/add/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@lerna/bootstrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-4.0.0.tgz", - "integrity": "sha512-RkS7UbeM2vu+kJnHzxNRCLvoOP9yGNgkzRdy4UV2hNalD7EP41bLvRVOwRYQ7fhc2QcbhnKNdOBihYRL0LcKtw==", + "node_modules/@jest/core/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": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/has-npm-version": "4.0.0", - "@lerna/npm-install": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/symlink-binary": "4.0.0", - "@lerna/symlink-dependencies": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "get-port": "^5.1.1", - "multimatch": "^5.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1", - "read-package-tree": "^5.3.1", - "semver": "^7.3.4" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/bootstrap/node_modules/@lerna/validation-error": { + "node_modules/@jest/core/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "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/@jest/core/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/@jest/core/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "npmlog": "^4.1.2" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8.6" } }, - "node_modules/@lerna/bootstrap/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/@jest/core/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=10" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/bootstrap/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/bootstrap/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/bootstrap/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/@jest/core/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "is-number": "^7.0.0" }, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=8.0" + } + }, + "node_modules/@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/bootstrap/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/@jest/environment/node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@types/node": "*" + }, + "engines": { + "node": ">= 10.14.2" + } }, - "node_modules/@lerna/changed": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-4.0.0.tgz", - "integrity": "sha512-cD+KuPRp6qiPOD+BO6S6SN5cARspIaWSOqGBpGnYzLb4uWT8Vk4JzKyYtc8ym1DIwyoFXHosXt8+GDAgR8QrgQ==", + "node_modules/@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", "dev": true, "dependencies": { - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/listable": "4.0.0", - "@lerna/output": "4.0.0" + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/check-working-tree": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-4.0.0.tgz", - "integrity": "sha512-/++bxM43jYJCshBiKP5cRlCTwSJdRSxVmcDAXM+1oUewlZJVSVlnks5eO0uLxokVFvLhHlC5kHMc7gbVFPHv6Q==", + "node_modules/@jest/fake-timers/node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "dependencies": { - "@lerna/collect-uncommitted": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "@lerna/validation-error": "4.0.0" + "@jest/types": "^26.6.2", + "@types/node": "*" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/check-working-tree/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "node_modules/@jest/globals": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", "dev": true, "dependencies": { - "npmlog": "^4.1.2" + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/child-process": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-4.0.0.tgz", - "integrity": "sha512-XtCnmCT9eyVsUUHx6y/CTBYdV9g2Cr/VxyseTWBgfIur92/YKClfEtJTbOh94jRT62hlKLqSvux/UhxXVh613Q==", + "node_modules/@jest/reporters": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz", + "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.4", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^7.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" + }, + "optionalDependencies": { + "node-notifier": "^8.0.0" } }, - "node_modules/@lerna/child-process/node_modules/ansi-styles": { + "node_modules/@jest/reporters/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==", @@ -1109,7 +1632,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/child-process/node_modules/chalk": { + "node_modules/@jest/reporters/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -1125,7 +1648,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/child-process/node_modules/color-convert": { + "node_modules/@jest/reporters/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==", @@ -1137,7 +1660,7 @@ "node": ">=7.0.0" } }, - "node_modules/@lerna/child-process/node_modules/has-flag": { + "node_modules/@jest/reporters/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==", @@ -1146,7 +1669,7 @@ "node": ">=8" } }, - "node_modules/@lerna/child-process/node_modules/supports-color": { + "node_modules/@jest/reporters/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -1158,50 +1681,78 @@ "node": ">=8" } }, - "node_modules/@lerna/clean": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-4.0.0.tgz", - "integrity": "sha512-uugG2iN9k45ITx2jtd8nEOoAtca8hNlDCUM0N3lFgU/b1mEQYAPRkqr1qs4FLRl/Y50ZJ41wUz1eazS+d/0osA==", + "node_modules/@jest/source-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", "dev": true, "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1" + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/cli": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-4.0.0.tgz", - "integrity": "sha512-Neaw3GzFrwZiRZv2g7g6NwFjs3er1vhraIniEs0jjVLPMNC4eata0na3GfE5yibkM/9d3gZdmihhZdZ3EBdvYA==", + "node_modules/@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", "dev": true, "dependencies": { - "@lerna/global-options": "4.0.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2", - "yargs": "^16.2.0" + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/cli/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/@jest/test-sequencer": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/cli/node_modules/ansi-styles": { + "node_modules/@jest/transform/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==", @@ -1216,18 +1767,35 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/cli/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/@jest/transform/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": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@lerna/cli/node_modules/color-convert": { + "node_modules/@jest/transform/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/@jest/transform/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==", @@ -1239,124 +1807,102 @@ "node": ">=7.0.0" } }, - "node_modules/@lerna/cli/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/@lerna/cli/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/transform/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=8" } }, - "node_modules/@lerna/cli/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/transform/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/@lerna/cli/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@jest/transform/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, "engines": { - "node": ">=8" + "node": ">=0.12.0" } }, - "node_modules/@lerna/cli/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/@jest/transform/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, - "node_modules/@lerna/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==", + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@lerna/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": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/cli/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/@jest/transform/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "is-number": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=8.0" } }, - "node_modules/@lerna/cli/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/@lerna/collect-uncommitted": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-4.0.0.tgz", - "integrity": "sha512-ufSTfHZzbx69YNj7KXQ3o66V4RC76ffOjwLX0q/ab//61bObJ41n03SiQEhSlmpP+gmFbTJ3/7pTe04AHX9m/g==", + "node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", "dev": true, "dependencies": { - "@lerna/child-process": "4.0.0", - "chalk": "^4.1.0", - "npmlog": "^4.1.2" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 10.14.2" } }, - "node_modules/@lerna/collect-uncommitted/node_modules/ansi-styles": { + "node_modules/@jest/types/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==", @@ -1371,7 +1917,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/collect-uncommitted/node_modules/chalk": { + "node_modules/@jest/types/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -1387,7 +1933,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/collect-uncommitted/node_modules/color-convert": { + "node_modules/@jest/types/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==", @@ -1399,7 +1945,7 @@ "node": ">=7.0.0" } }, - "node_modules/@lerna/collect-uncommitted/node_modules/has-flag": { + "node_modules/@jest/types/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==", @@ -1408,7 +1954,7 @@ "node": ">=8" } }, - "node_modules/@lerna/collect-uncommitted/node_modules/supports-color": { + "node_modules/@jest/types/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -1420,82 +1966,94 @@ "node": ">=8" } }, - "node_modules/@lerna/collect-updates": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-4.0.0.tgz", - "integrity": "sha512-bnNGpaj4zuxsEkyaCZLka9s7nMs58uZoxrRIPJ+nrmrZYp1V5rrd+7/NYTuunOhY2ug1sTBvTAxj3NZQ+JKnOw==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", "dev": true, "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "slash": "^3.0.0" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">= 10.18.0" + "node": ">=6.0.0" } }, - "node_modules/@lerna/command": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/command/-/command-4.0.0.tgz", - "integrity": "sha512-LM9g3rt5FsPNFqIHUeRwWXLNHJ5NKzOwmVKZ8anSp4e1SPrv2HNc1V02/9QyDDZK/w+5POXH5lxZUI1CHaOK/A==", + "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, - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/project": "4.0.0", - "@lerna/validation-error": "4.0.0", - "@lerna/write-log-file": "4.0.0", - "clone-deep": "^4.0.1", - "dedent": "^0.7.0", - "execa": "^5.0.0", - "is-ci": "^2.0.0", - "npmlog": "^4.1.2" - }, "engines": { - "node": ">= 10.18.0" + "node": ">=6.0.0" } }, - "node_modules/@lerna/command/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "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==", + "dev": true, + "engines": { + "node": ">=6.0.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.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", "dev": true, "dependencies": { - "npmlog": "^4.1.2" - }, + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jsbits/escape-regex-str": { + "version": "1.0.3", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 10.18.0" + "node": ">=4.2" } }, - "node_modules/@lerna/conventional-commits": { + "node_modules/@jsbits/get-package-version": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.2" + } + }, + "node_modules/@lerna/add": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-4.0.0.tgz", - "integrity": "sha512-CSUQRjJHFrH8eBn7+wegZLV3OrNc0Y1FehYfYGhjLE2SIfpCL4bmfu/ViYuHh9YjwHaA+4SX6d3hR+xkeseKmw==", "dev": true, + "license": "MIT", "dependencies": { + "@lerna/bootstrap": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/npm-conf": "4.0.0", "@lerna/validation-error": "4.0.0", - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-core": "^4.2.2", - "conventional-recommended-bump": "^6.1.0", - "fs-extra": "^9.1.0", - "get-stream": "^6.0.0", - "lodash.template": "^4.5.0", + "dedent": "^0.7.0", "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "pify": "^5.0.0", + "p-map": "^4.0.0", + "pacote": "^11.2.6", "semver": "^7.3.4" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/conventional-commits/node_modules/@lerna/validation-error": { + "node_modules/@lerna/add/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -1503,38 +2061,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/conventional-commits/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/@lerna/conventional-commits/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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna/conventional-commits/node_modules/hosted-git-info": { + "node_modules/@lerna/add/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1542,23 +2072,10 @@ "node": ">=10" } }, - "node_modules/@lerna/conventional-commits/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/conventional-commits/node_modules/lru-cache": { + "node_modules/@lerna/add/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1566,11 +2083,10 @@ "node": ">=10" } }, - "node_modules/@lerna/conventional-commits/node_modules/npm-package-arg": { + "node_modules/@lerna/add/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -1580,23 +2096,10 @@ "node": ">=10" } }, - "node_modules/@lerna/conventional-commits/node_modules/pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna/conventional-commits/node_modules/semver": { + "node_modules/@lerna/add/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1607,510 +2110,498 @@ "node": ">=10" } }, - "node_modules/@lerna/conventional-commits/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@lerna/conventional-commits/node_modules/yallist": { + "node_modules/@lerna/add/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, - "node_modules/@lerna/create": { + "node_modules/@lerna/bootstrap": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-4.0.0.tgz", - "integrity": "sha512-mVOB1niKByEUfxlbKTM1UNECWAjwUdiioIbRQZEeEabtjCL69r9rscIsjlGyhGWCfsdAG5wfq4t47nlDXdLLag==", "dev": true, + "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", "@lerna/command": "4.0.0", - "@lerna/npm-conf": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/has-npm-version": "4.0.0", + "@lerna/npm-install": "4.0.0", + "@lerna/package-graph": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/rimraf-dir": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/symlink-binary": "4.0.0", + "@lerna/symlink-dependencies": "4.0.0", "@lerna/validation-error": "4.0.0", "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "init-package-json": "^2.0.2", + "get-port": "^5.1.1", + "multimatch": "^5.0.0", "npm-package-arg": "^8.1.0", - "p-reduce": "^2.1.0", - "pacote": "^11.2.6", - "pify": "^5.0.0", - "semver": "^7.3.4", - "slash": "^3.0.0", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0", - "whatwg-url": "^8.4.0", - "yargs-parser": "20.2.4" + "npmlog": "^4.1.2", + "p-map": "^4.0.0", + "p-map-series": "^2.1.0", + "p-waterfall": "^2.1.1", + "read-package-tree": "^5.3.1", + "semver": "^7.3.4" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/create-symlink": { + "node_modules/@lerna/bootstrap/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-4.0.0.tgz", - "integrity": "sha512-I0phtKJJdafUiDwm7BBlEUOtogmu8+taxq6PtIrxZbllV9hWg59qkpuIsiFp+no7nfRVuaasNYHwNUhDAVQBig==", "dev": true, + "license": "MIT", "dependencies": { - "cmd-shim": "^4.1.0", - "fs-extra": "^9.1.0", "npmlog": "^4.1.2" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/create-symlink/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/@lerna/bootstrap/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/@lerna/create-symlink/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna/bootstrap/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "universalify": "^2.0.0" + "yallist": "^4.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/create-symlink/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=10" } }, - "node_modules/@lerna/create/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "node_modules/@lerna/bootstrap/node_modules/npm-package-arg": { + "version": "8.1.5", "dev": true, + "license": "ISC", "dependencies": { - "npmlog": "^4.1.2" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" } }, - "node_modules/@lerna/create/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/@lerna/bootstrap/node_modules/semver": { + "version": "7.3.5", "dev": true, + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/@lerna/create/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/@lerna/bootstrap/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@lerna/changed": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" + "@lerna/collect-updates": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/listable": "4.0.0", + "@lerna/output": "4.0.0" }, "engines": { - "node": ">=10" + "node": ">= 10.18.0" } }, - "node_modules/@lerna/create/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna/check-working-tree": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "@lerna/collect-uncommitted": "4.0.0", + "@lerna/describe-ref": "4.0.0", + "@lerna/validation-error": "4.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 10.18.0" } }, - "node_modules/@lerna/create/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@lerna/check-working-tree/node_modules/@lerna/validation-error": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "npmlog": "^4.1.2" }, "engines": { - "node": ">=10" + "node": ">= 10.18.0" } }, - "node_modules/@lerna/create/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/@lerna/child-process": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "chalk": "^4.1.0", + "execa": "^5.0.0", + "strong-log-transformer": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">= 10.18.0" } }, - "node_modules/@lerna/create/node_modules/pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "node_modules/@lerna/child-process/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/create/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/@lerna/child-process/node_modules/chalk": { + "version": "4.1.2", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/create/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/@lerna/child-process/node_modules/color-convert": { + "version": "2.0.1", "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=7.0.0" } }, - "node_modules/@lerna/create/node_modules/yallist": { + "node_modules/@lerna/child-process/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@lerna/create/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/describe-ref": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-4.0.0.tgz", - "integrity": "sha512-eTU5+xC4C5Gcgz+Ey4Qiw9nV2B4JJbMulsYJMW8QjGcGh8zudib7Sduj6urgZXUYNyhYpRs+teci9M2J8u+UvQ==", + "node_modules/@lerna/child-process/node_modules/supports-color": { + "version": "7.2.0", "dev": true, + "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "npmlog": "^4.1.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/diff": { + "node_modules/@lerna/clean": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-4.0.0.tgz", - "integrity": "sha512-jYPKprQVg41+MUMxx6cwtqsNm0Yxx9GDEwdiPLwcUTFx+/qKCEwifKNJ1oGIPBxyEHX2PFCOjkK39lHoj2qiag==", "dev": true, + "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", "@lerna/command": "4.0.0", - "@lerna/validation-error": "4.0.0", - "npmlog": "^4.1.2" + "@lerna/filter-options": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/rimraf-dir": "4.0.0", + "p-map": "^4.0.0", + "p-map-series": "^2.1.0", + "p-waterfall": "^2.1.1" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/diff/node_modules/@lerna/validation-error": { + "node_modules/@lerna/cli": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { - "npmlog": "^4.1.2" + "@lerna/global-options": "4.0.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2", + "yargs": "^16.2.0" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/exec": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-4.0.0.tgz", - "integrity": "sha512-VGXtL/b/JfY84NB98VWZpIExfhLOzy0ozm/0XaS4a2SmkAJc5CeUfrhvHxxkxiTBLkU+iVQUyYEoAT0ulQ8PCw==", + "node_modules/@lerna/cli/node_modules/ansi-regex": { + "version": "5.0.1", "dev": true, - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/profiler": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "p-map": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/exec/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "node_modules/@lerna/cli/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, + "license": "MIT", "dependencies": { - "npmlog": "^4.1.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/filter-options": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-4.0.0.tgz", - "integrity": "sha512-vV2ANOeZhOqM0rzXnYcFFCJ/kBWy/3OA58irXih9AMTAlQLymWAK0akWybl++sUJ4HB9Hx12TOqaXbYS2NM5uw==", + "node_modules/@lerna/cli/node_modules/cliui": { + "version": "7.0.4", "dev": true, + "license": "ISC", "dependencies": { - "@lerna/collect-updates": "4.0.0", - "@lerna/filter-packages": "4.0.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2" - }, - "engines": { - "node": ">= 10.18.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/@lerna/filter-packages": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-4.0.0.tgz", - "integrity": "sha512-+4AJIkK7iIiOaqCiVTYJxh/I9qikk4XjNQLhE3kixaqgMuHl1NQ99qXRR0OZqAWB9mh8Z1HA9bM5K1HZLBTOqA==", + "node_modules/@lerna/cli/node_modules/color-convert": { + "version": "2.0.1", "dev": true, + "license": "MIT", "dependencies": { - "@lerna/validation-error": "4.0.0", - "multimatch": "^5.0.0", - "npmlog": "^4.1.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 10.18.0" + "node": ">=7.0.0" } }, - "node_modules/@lerna/filter-packages/node_modules/@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "node_modules/@lerna/cli/node_modules/emoji-regex": { + "version": "8.0.0", "dev": true, - "dependencies": { - "npmlog": "^4.1.2" - }, + "license": "MIT" + }, + "node_modules/@lerna/cli/node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/@lerna/get-npm-exec-opts": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-4.0.0.tgz", - "integrity": "sha512-yvmkerU31CTWS2c7DvmAWmZVeclPBqI7gPVr5VATUKNWJ/zmVcU4PqbYoLu92I9Qc4gY1TuUplMNdNuZTSL7IQ==", + "node_modules/@lerna/cli/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@lerna/cli/node_modules/string-width": { + "version": "4.2.3", "dev": true, + "license": "MIT", "dependencies": { - "npmlog": "^4.1.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/get-packed": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-4.0.0.tgz", - "integrity": "sha512-rfWONRsEIGyPJTxFzC8ECb3ZbsDXJbfqWYyeeQQDrJRPnEJErlltRLPLgC2QWbxFgFPsoDLeQmFHJnf0iDfd8w==", + "node_modules/@lerna/cli/node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, + "license": "MIT", "dependencies": { - "fs-extra": "^9.1.0", - "ssri": "^8.0.1", - "tar": "^6.1.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/get-packed/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/@lerna/cli/node_modules/wrap-ansi": { + "version": "7.0.0", "dev": true, + "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@lerna/cli/node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/@lerna/get-packed/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna/cli/node_modules/yargs": { + "version": "16.2.0", "dev": true, + "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=10" } }, - "node_modules/@lerna/get-packed/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/@lerna/cli/node_modules/yargs-parser": { + "version": "20.2.9", "dev": true, + "license": "ISC", "engines": { - "node": ">= 10.0.0" + "node": ">=10" } }, - "node_modules/@lerna/github-client": { + "node_modules/@lerna/collect-uncommitted": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-4.0.0.tgz", - "integrity": "sha512-2jhsldZtTKXYUBnOm23Lb0Fx8G4qfSXF9y7UpyUgWUj+YZYd+cFxSuorwQIgk5P4XXrtVhsUesIsli+BYSThiw==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/child-process": "4.0.0", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^18.1.0", - "git-url-parse": "^11.4.4", + "chalk": "^4.1.0", "npmlog": "^4.1.2" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/gitlab-client": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-4.0.0.tgz", - "integrity": "sha512-OMUpGSkeDWFf7BxGHlkbb35T7YHqVFCwBPSIR6wRsszY8PAzCYahtH3IaJzEJyUg6vmZsNl0FSr3pdA2skhxqA==", + "node_modules/@lerna/collect-uncommitted/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, + "license": "MIT", "dependencies": { - "node-fetch": "^2.6.1", - "npmlog": "^4.1.2", - "whatwg-url": "^8.4.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@lerna/global-options": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-4.0.0.tgz", - "integrity": "sha512-TRMR8afAHxuYBHK7F++Ogop2a82xQjoGna1dvPOY6ltj/pEx59pdgcJfYcynYqMkFIk8bhLJJN9/ndIfX29FTQ==", + "node_modules/@lerna/collect-uncommitted/node_modules/chalk": { + "version": "4.1.2", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/has-npm-version": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-4.0.0.tgz", - "integrity": "sha512-LQ3U6XFH8ZmLCsvsgq1zNDqka0Xzjq5ibVN+igAI5ccRWNaUsE/OcmsyMr50xAtNQMYMzmpw5GVLAivT2/YzCg==", + "node_modules/@lerna/collect-uncommitted/node_modules/color-convert": { + "version": "2.0.1", "dev": true, + "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "semver": "^7.3.4" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 10.18.0" + "node": ">=7.0.0" } }, - "node_modules/@lerna/has-npm-version/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@lerna/collect-uncommitted/node_modules/has-flag": { + "version": "4.0.0", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/has-npm-version/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/@lerna/collect-uncommitted/node_modules/supports-color": { + "version": "7.2.0", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@lerna/has-npm-version/node_modules/yallist": { + "node_modules/@lerna/collect-updates": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/describe-ref": "4.0.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">= 10.18.0" + } }, - "node_modules/@lerna/import": { + "node_modules/@lerna/command": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/import/-/import-4.0.0.tgz", - "integrity": "sha512-FaIhd+4aiBousKNqC7TX1Uhe97eNKf5/SC7c5WZANVWtC7aBWdmswwDt3usrzCNpj6/Wwr9EtEbYROzxKH8ffg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", + "@lerna/package-graph": "4.0.0", + "@lerna/project": "4.0.0", "@lerna/validation-error": "4.0.0", + "@lerna/write-log-file": "4.0.0", + "clone-deep": "^4.0.1", "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "p-map-series": "^2.1.0" + "execa": "^5.0.0", + "is-ci": "^2.0.0", + "npmlog": "^4.1.2" }, "engines": { "node": ">= 10.18.0" } }, - "node_modules/@lerna/import/node_modules/@lerna/validation-error": { + "node_modules/@lerna/command/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -2118,146 +2609,521 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/import/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/@lerna/conventional-commits": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@lerna/validation-error": "4.0.0", + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-core": "^4.2.2", + "conventional-recommended-bump": "^6.1.0", + "fs-extra": "^9.1.0", + "get-stream": "^6.0.0", + "lodash.template": "^4.5.0", + "npm-package-arg": "^8.1.0", + "npmlog": "^4.1.2", + "pify": "^5.0.0", + "semver": "^7.3.4" }, "engines": { - "node": ">=10" + "node": ">= 10.18.0" } }, - "node_modules/@lerna/import/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna/conventional-commits/node_modules/@lerna/validation-error": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "npmlog": "^4.1.2" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 10.18.0" } }, - "node_modules/@lerna/import/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/@lerna/conventional-commits/node_modules/get-stream": { + "version": "6.0.1", "dev": true, + "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna/info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/info/-/info-4.0.0.tgz", - "integrity": "sha512-8Uboa12kaCSZEn4XRfPz5KU9XXoexSPS4oeYGj76s2UQb1O1GdnEyfjyNWoUl1KlJ2i/8nxUskpXIftoFYH0/Q==", + "node_modules/@lerna/conventional-commits/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/output": "4.0.0", - "envinfo": "^7.7.4" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" } }, - "node_modules/@lerna/init": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/init/-/init-4.0.0.tgz", - "integrity": "sha512-wY6kygop0BCXupzWj5eLvTUqdR7vIAm0OgyV9WHpMYQGfs1V22jhztt8mtjCloD/O0nEe4tJhdG62XU5aYmPNQ==", + "node_modules/@lerna/conventional-commits/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "write-json-file": "^4.3.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" } }, - "node_modules/@lerna/init/node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "node_modules/@lerna/conventional-commits/node_modules/npm-package-arg": { + "version": "8.1.5", "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@lerna/init/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/@lerna/conventional-commits/node_modules/pify": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@lerna/conventional-commits/node_modules/semver": { + "version": "7.3.5", "dev": true, + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/@lerna/init/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/@lerna/conventional-commits/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@lerna/create": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/npm-conf": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "fs-extra": "^9.1.0", + "globby": "^11.0.2", + "init-package-json": "^2.0.2", + "npm-package-arg": "^8.1.0", + "p-reduce": "^2.1.0", + "pacote": "^11.2.6", + "pify": "^5.0.0", + "semver": "^7.3.4", + "slash": "^3.0.0", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^3.0.0", + "whatwg-url": "^8.4.0", + "yargs-parser": "20.2.4" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/create-symlink": { + "version": "4.0.0", "dev": true, + "license": "MIT", + "dependencies": { + "cmd-shim": "^4.1.0", + "fs-extra": "^9.1.0", + "npmlog": "^4.1.2" + }, "engines": { - "node": ">=8" + "node": ">= 10.18.0" } }, - "node_modules/@lerna/init/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@lerna/create/node_modules/@lerna/validation-error": { + "version": "4.0.0", "dev": true, + "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "npmlog": "^4.1.2" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 10.18.0" } }, - "node_modules/@lerna/init/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/@lerna/create/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "semver": "^6.0.0" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/@lerna/create/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/create/node_modules/npm-package-arg": { + "version": "8.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/create/node_modules/pify": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna/init/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@lerna/create/node_modules/semver": { + "version": "7.3.5", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/create/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@lerna/create/node_modules/yargs-parser": { + "version": "20.2.4", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/describe-ref": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/diff": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/validation-error": "4.0.0", + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/diff/node_modules/@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/exec": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/profiler": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/validation-error": "4.0.0", + "p-map": "^4.0.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/exec/node_modules/@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/filter-options": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/collect-updates": "4.0.0", + "@lerna/filter-packages": "4.0.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/filter-packages": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/validation-error": "4.0.0", + "multimatch": "^5.0.0", + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/filter-packages/node_modules/@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/get-npm-exec-opts": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/get-packed": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^9.1.0", + "ssri": "^8.0.1", + "tar": "^6.1.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/github-client": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@octokit/plugin-enterprise-rest": "^6.0.1", + "@octokit/rest": "^18.1.0", + "git-url-parse": "^11.4.4", + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/gitlab-client": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "npmlog": "^4.1.2", + "whatwg-url": "^8.4.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/global-options": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/has-npm-version": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/has-npm-version/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/has-npm-version/node_modules/semver": { + "version": "7.3.5", "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@lerna/has-npm-version/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@lerna/import": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "fs-extra": "^9.1.0", + "p-map-series": "^2.1.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/import/node_modules/@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "npmlog": "^4.1.2" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/info": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/command": "4.0.0", + "@lerna/output": "4.0.0", + "envinfo": "^7.7.4" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/init": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "fs-extra": "^9.1.0", + "p-map": "^4.0.0", + "write-json-file": "^4.3.0" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "node_modules/@lerna/init/node_modules/detect-indent": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@lerna/init/node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/@lerna/init/node_modules/sort-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-obj": "^2.0.0" }, @@ -2268,20 +3134,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna/init/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/init/node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -2291,9 +3147,8 @@ }, "node_modules/@lerna/init/node_modules/write-json-file": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^6.0.0", "graceful-fs": "^4.1.15", @@ -2311,9 +3166,8 @@ }, "node_modules/@lerna/link": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/link/-/link-4.0.0.tgz", - "integrity": "sha512-KlvPi7XTAcVOByfaLlOeYOfkkDcd+bejpHMCd1KcArcFTwijOwXOVi24DYomIeHvy6HsX/IUquJ4PPUJIeB4+w==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/command": "4.0.0", "@lerna/package-graph": "4.0.0", @@ -2327,9 +3181,8 @@ }, "node_modules/@lerna/list": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/list/-/list-4.0.0.tgz", - "integrity": "sha512-L2B5m3P+U4Bif5PultR4TI+KtW+SArwq1i75QZ78mRYxPc0U/piau1DbLOmwrdqr99wzM49t0Dlvl6twd7GHFg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/command": "4.0.0", "@lerna/filter-options": "4.0.0", @@ -2342,9 +3195,8 @@ }, "node_modules/@lerna/listable": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-4.0.0.tgz", - "integrity": "sha512-/rPOSDKsOHs5/PBLINZOkRIX1joOXUXEtyUs5DHLM8q6/RP668x/1lFhw6Dx7/U+L0+tbkpGtZ1Yt0LewCLgeQ==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/query-graph": "4.0.0", "chalk": "^4.1.0", @@ -2356,9 +3208,8 @@ }, "node_modules/@lerna/listable/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2371,9 +3222,8 @@ }, "node_modules/@lerna/listable/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2387,9 +3237,8 @@ }, "node_modules/@lerna/listable/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2399,18 +3248,16 @@ }, "node_modules/@lerna/listable/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/listable/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -2420,9 +3267,8 @@ }, "node_modules/@lerna/log-packed": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-4.0.0.tgz", - "integrity": "sha512-+dpCiWbdzgMAtpajLToy9PO713IHoE6GV/aizXycAyA07QlqnkpaBNZ8DW84gHdM1j79TWockGJo9PybVhrrZQ==", "dev": true, + "license": "MIT", "dependencies": { "byte-size": "^7.0.0", "columnify": "^1.5.4", @@ -2435,9 +3281,8 @@ }, "node_modules/@lerna/npm-conf": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-4.0.0.tgz", - "integrity": "sha512-uS7H02yQNq3oejgjxAxqq/jhwGEE0W0ntr8vM3EfpCW1F/wZruwQw+7bleJQ9vUBjmdXST//tk8mXzr5+JXCfw==", "dev": true, + "license": "MIT", "dependencies": { "config-chain": "^1.1.12", "pify": "^5.0.0" @@ -2448,9 +3293,8 @@ }, "node_modules/@lerna/npm-conf/node_modules/pify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2460,9 +3304,8 @@ }, "node_modules/@lerna/npm-dist-tag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-4.0.0.tgz", - "integrity": "sha512-F20sg28FMYTgXqEQihgoqSfwmq+Id3zT23CnOwD+XQMPSy9IzyLf1fFVH319vXIw6NF6Pgs4JZN2Qty6/CQXGw==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/otplease": "4.0.0", "npm-package-arg": "^8.1.0", @@ -2475,9 +3318,8 @@ }, "node_modules/@lerna/npm-dist-tag/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2487,9 +3329,8 @@ }, "node_modules/@lerna/npm-dist-tag/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2499,9 +3340,8 @@ }, "node_modules/@lerna/npm-dist-tag/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -2513,9 +3353,8 @@ }, "node_modules/@lerna/npm-dist-tag/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2528,15 +3367,13 @@ }, "node_modules/@lerna/npm-dist-tag/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/npm-install": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-4.0.0.tgz", - "integrity": "sha512-aKNxq2j3bCH3eXl3Fmu4D54s/YLL9WSwV8W7X2O25r98wzrO38AUN6AB9EtmAx+LV/SP15et7Yueg9vSaanRWg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/child-process": "4.0.0", "@lerna/get-npm-exec-opts": "4.0.0", @@ -2550,62 +3387,32 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/npm-install/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/@lerna/npm-install/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/@lerna/npm-install/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/@lerna/npm-install/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/@lerna/npm-install/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/npm-install/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@lerna/npm-install/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "node_modules/@lerna/npm-install/node_modules/make-dir": { + "version": "2.1.0", "dev": true, + "license": "MIT", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -2616,18 +3423,16 @@ }, "node_modules/@lerna/npm-install/node_modules/make-dir/node_modules/semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/@lerna/npm-install/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -2639,18 +3444,16 @@ }, "node_modules/@lerna/npm-install/node_modules/pify": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@lerna/npm-install/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2663,27 +3466,16 @@ }, "node_modules/@lerna/npm-install/node_modules/type-fest": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=6" } }, - "node_modules/@lerna/npm-install/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/npm-install/node_modules/write-json-file": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -2698,9 +3490,8 @@ }, "node_modules/@lerna/npm-install/node_modules/write-pkg": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", "dev": true, + "license": "MIT", "dependencies": { "sort-keys": "^2.0.0", "type-fest": "^0.4.1", @@ -2712,15 +3503,13 @@ }, "node_modules/@lerna/npm-install/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/npm-publish": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-4.0.0.tgz", - "integrity": "sha512-vQb7yAPRo5G5r77DRjHITc9piR9gvEKWrmfCH7wkfBnGWEqu7n8/4bFQ7lhnkujvc8RXOsYpvbMQkNfkYibD/w==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/otplease": "4.0.0", "@lerna/run-lifecycle": "4.0.0", @@ -2735,26 +3524,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/npm-publish/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/@lerna/npm-publish/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2762,23 +3535,10 @@ "node": ">=10" } }, - "node_modules/@lerna/npm-publish/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/@lerna/npm-publish/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2788,9 +3548,8 @@ }, "node_modules/@lerna/npm-publish/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -2802,9 +3561,8 @@ }, "node_modules/@lerna/npm-publish/node_modules/pify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2814,9 +3572,8 @@ }, "node_modules/@lerna/npm-publish/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2827,26 +3584,15 @@ "node": ">=10" } }, - "node_modules/@lerna/npm-publish/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/npm-publish/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/npm-run-script": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-4.0.0.tgz", - "integrity": "sha512-Jmyh9/IwXJjOXqKfIgtxi0bxi1pUeKe5bD3S81tkcy+kyng/GNj9WSqD5ZggoNP2NP//s4CLDAtUYLdP7CU9rA==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/child-process": "4.0.0", "@lerna/get-npm-exec-opts": "4.0.0", @@ -2858,9 +3604,8 @@ }, "node_modules/@lerna/otplease": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-4.0.0.tgz", - "integrity": "sha512-Sgzbqdk1GH4psNiT6hk+BhjOfIr/5KhGBk86CEfHNJTk9BK4aZYyJD4lpDbDdMjIV4g03G7pYoqHzH765T4fxw==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/prompt": "4.0.0" }, @@ -2870,9 +3615,8 @@ }, "node_modules/@lerna/output": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/output/-/output-4.0.0.tgz", - "integrity": "sha512-Un1sHtO1AD7buDQrpnaYTi2EG6sLF+KOPEAMxeUYG5qG3khTs2Zgzq5WE3dt2N/bKh7naESt20JjIW6tBELP0w==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -2882,9 +3626,8 @@ }, "node_modules/@lerna/pack-directory": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-4.0.0.tgz", - "integrity": "sha512-NJrmZNmBHS+5aM+T8N6FVbaKFScVqKlQFJNY2k7nsJ/uklNKsLLl6VhTQBPwMTbf6Tf7l6bcKzpy7aePuq9UiQ==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/get-packed": "4.0.0", "@lerna/package": "4.0.0", @@ -2900,9 +3643,8 @@ }, "node_modules/@lerna/package": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/package/-/package-4.0.0.tgz", - "integrity": "sha512-l0M/izok6FlyyitxiQKr+gZLVFnvxRQdNhzmQ6nRnN9dvBJWn+IxxpM+cLqGACatTnyo9LDzNTOj2Db3+s0s8Q==", "dev": true, + "license": "MIT", "dependencies": { "load-json-file": "^6.2.0", "npm-package-arg": "^8.1.0", @@ -2914,9 +3656,8 @@ }, "node_modules/@lerna/package-graph": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-4.0.0.tgz", - "integrity": "sha512-QED2ZCTkfXMKFoTGoccwUzjHtZMSf3UKX14A4/kYyBms9xfFsesCZ6SLI5YeySEgcul8iuIWfQFZqRw+Qrjraw==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/prerelease-id-from-version": "4.0.0", "@lerna/validation-error": "4.0.0", @@ -2930,9 +3671,8 @@ }, "node_modules/@lerna/package-graph/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -2942,9 +3682,8 @@ }, "node_modules/@lerna/package-graph/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2954,9 +3693,8 @@ }, "node_modules/@lerna/package-graph/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -2966,9 +3704,8 @@ }, "node_modules/@lerna/package-graph/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -2980,9 +3717,8 @@ }, "node_modules/@lerna/package-graph/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2995,15 +3731,13 @@ }, "node_modules/@lerna/package-graph/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/package/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3013,9 +3747,8 @@ }, "node_modules/@lerna/package/node_modules/load-json-file": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.15", "parse-json": "^5.0.0", @@ -3028,9 +3761,8 @@ }, "node_modules/@lerna/package/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3040,9 +3772,8 @@ }, "node_modules/@lerna/package/node_modules/make-dir": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -3053,18 +3784,16 @@ }, "node_modules/@lerna/package/node_modules/make-dir/node_modules/semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } }, "node_modules/@lerna/package/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -3076,9 +3805,8 @@ }, "node_modules/@lerna/package/node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -3094,18 +3822,16 @@ }, "node_modules/@lerna/package/node_modules/pify": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@lerna/package/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3118,27 +3844,24 @@ }, "node_modules/@lerna/package/node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/package/node_modules/type-fest": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/@lerna/package/node_modules/write-json-file": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -3153,9 +3876,8 @@ }, "node_modules/@lerna/package/node_modules/write-pkg": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", "dev": true, + "license": "MIT", "dependencies": { "sort-keys": "^2.0.0", "type-fest": "^0.4.1", @@ -3167,24 +3889,21 @@ }, "node_modules/@lerna/package/node_modules/write-pkg/node_modules/type-fest": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=6" } }, "node_modules/@lerna/package/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/prerelease-id-from-version": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-4.0.0.tgz", - "integrity": "sha512-GQqguzETdsYRxOSmdFZ6zDBXDErIETWOqomLERRY54f4p+tk4aJjoVdd9xKwehC9TBfIFvlRbL1V9uQGHh1opg==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.3.4" }, @@ -3194,9 +3913,8 @@ }, "node_modules/@lerna/prerelease-id-from-version/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3206,9 +3924,8 @@ }, "node_modules/@lerna/prerelease-id-from-version/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3221,15 +3938,13 @@ }, "node_modules/@lerna/prerelease-id-from-version/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/profiler": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-4.0.0.tgz", - "integrity": "sha512-/BaEbqnVh1LgW/+qz8wCuI+obzi5/vRE8nlhjPzdEzdmWmZXuCKyWSEzAyHOJWw1ntwMiww5dZHhFQABuoFz9Q==", "dev": true, + "license": "MIT", "dependencies": { "fs-extra": "^9.1.0", "npmlog": "^4.1.2", @@ -3239,47 +3954,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/profiler/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/@lerna/profiler/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/profiler/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/project": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/project/-/project-4.0.0.tgz", - "integrity": "sha512-o0MlVbDkD5qRPkFKlBZsXZjoNTWPyuL58564nSfZJ6JYNmgAptnWPB2dQlAc7HWRZkmnC2fCkEdoU+jioPavbg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/package": "4.0.0", "@lerna/validation-error": "4.0.0", @@ -3300,9 +3978,8 @@ }, "node_modules/@lerna/project/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -3312,9 +3989,8 @@ }, "node_modules/@lerna/project/node_modules/cosmiconfig": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -3328,18 +4004,16 @@ }, "node_modules/@lerna/project/node_modules/detect-indent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/dot-prop": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -3352,9 +4026,8 @@ }, "node_modules/@lerna/project/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, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3364,9 +4037,8 @@ }, "node_modules/@lerna/project/node_modules/import-fresh": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3380,18 +4052,16 @@ }, "node_modules/@lerna/project/node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@lerna/project/node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -3401,27 +4071,24 @@ }, "node_modules/@lerna/project/node_modules/is-obj": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/is-plain-obj": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/load-json-file": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.15", "parse-json": "^5.0.0", @@ -3432,26 +4099,10 @@ "node": ">=8" } }, - "node_modules/@lerna/project/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@lerna/project/node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -3467,36 +4118,24 @@ }, "node_modules/@lerna/project/node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@lerna/project/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@lerna/project/node_modules/sort-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-obj": "^2.0.0" }, @@ -3509,27 +4148,24 @@ }, "node_modules/@lerna/project/node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/type-fest": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/@lerna/project/node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -3539,9 +4175,8 @@ }, "node_modules/@lerna/project/node_modules/write-json-file": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^6.0.0", "graceful-fs": "^4.1.15", @@ -3559,9 +4194,8 @@ }, "node_modules/@lerna/prompt": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-4.0.0.tgz", - "integrity": "sha512-4Ig46oCH1TH5M7YyTt53fT6TuaKMgqUUaqdgxvp6HP6jtdak6+amcsqB8YGz2eQnw/sdxunx84DfI9XpoLj4bQ==", "dev": true, + "license": "MIT", "dependencies": { "inquirer": "^7.3.3", "npmlog": "^4.1.2" @@ -3572,9 +4206,8 @@ }, "node_modules/@lerna/publish": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-4.0.0.tgz", - "integrity": "sha512-K8jpqjHrChH22qtkytA5GRKIVFEtqBF6JWj1I8dWZtHs4Jywn8yB1jQ3BAMLhqmDJjWJtRck0KXhQQKzDK2UPg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/check-working-tree": "4.0.0", "@lerna/child-process": "4.0.0", @@ -3611,9 +4244,8 @@ }, "node_modules/@lerna/publish/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -3621,26 +4253,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/publish/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/@lerna/publish/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3648,23 +4264,10 @@ "node": ">=10" } }, - "node_modules/@lerna/publish/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/@lerna/publish/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3674,9 +4277,8 @@ }, "node_modules/@lerna/publish/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -3688,9 +4290,8 @@ }, "node_modules/@lerna/publish/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3701,26 +4302,15 @@ "node": ">=10" } }, - "node_modules/@lerna/publish/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/publish/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/pulse-till-done": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-4.0.0.tgz", - "integrity": "sha512-Frb4F7QGckaybRhbF7aosLsJ5e9WuH7h0KUkjlzSByVycxY91UZgaEIVjS2oN9wQLrheLMHl6SiFY0/Pvo0Cxg==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -3730,9 +4320,8 @@ }, "node_modules/@lerna/query-graph": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-4.0.0.tgz", - "integrity": "sha512-YlP6yI3tM4WbBmL9GCmNDoeQyzcyg1e4W96y/PKMZa5GbyUvkS2+Jc2kwPD+5KcXou3wQZxSPzR3Te5OenaDdg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/package-graph": "4.0.0" }, @@ -3742,9 +4331,8 @@ }, "node_modules/@lerna/resolve-symlink": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-4.0.0.tgz", - "integrity": "sha512-RtX8VEUzqT+uLSCohx8zgmjc6zjyRlh6i/helxtZTMmc4+6O4FS9q5LJas2uGO2wKvBlhcD6siibGt7dIC3xZA==", "dev": true, + "license": "MIT", "dependencies": { "fs-extra": "^9.1.0", "npmlog": "^4.1.2", @@ -3754,47 +4342,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/resolve-symlink/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/@lerna/resolve-symlink/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/resolve-symlink/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/rimraf-dir": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-4.0.0.tgz", - "integrity": "sha512-QNH9ABWk9mcMJh2/muD9iYWBk1oQd40y6oH+f3wwmVGKYU5YJD//+zMiBI13jxZRtwBx0vmBZzkBkK1dR11cBg==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/child-process": "4.0.0", "npmlog": "^4.1.2", @@ -3807,18 +4358,16 @@ }, "node_modules/@lerna/rimraf-dir/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/rimraf-dir/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -3831,9 +4380,8 @@ }, "node_modules/@lerna/run": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run/-/run-4.0.0.tgz", - "integrity": "sha512-9giulCOzlMPzcZS/6Eov6pxE9gNTyaXk0Man+iCIdGJNMrCnW7Dme0Z229WWP/UoxDKg71F2tMsVVGDiRd8fFQ==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/command": "4.0.0", "@lerna/filter-options": "4.0.0", @@ -3851,9 +4399,8 @@ }, "node_modules/@lerna/run-lifecycle": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-4.0.0.tgz", - "integrity": "sha512-IwxxsajjCQQEJAeAaxF8QdEixfI7eLKNm4GHhXHrgBu185JcwScFZrj9Bs+PFKxwb+gNLR4iI5rpUdY8Y0UdGQ==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/npm-conf": "4.0.0", "npm-lifecycle": "^3.1.5", @@ -3865,9 +4412,8 @@ }, "node_modules/@lerna/run-topologically": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-4.0.0.tgz", - "integrity": "sha512-EVZw9hGwo+5yp+VL94+NXRYisqgAlj0jWKWtAIynDCpghRxCE5GMO3xrQLmQgqkpUl9ZxQFpICgYv5DW4DksQA==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/query-graph": "4.0.0", "p-queue": "^6.6.2" @@ -3878,9 +4424,8 @@ }, "node_modules/@lerna/run/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -3890,9 +4435,8 @@ }, "node_modules/@lerna/symlink-binary": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-4.0.0.tgz", - "integrity": "sha512-zualodWC4q1QQc1pkz969hcFeWXOsVYZC5AWVtAPTDfLl+TwM7eG/O6oP+Rr3fFowspxo6b1TQ6sYfDV6HXNWA==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/create-symlink": "4.0.0", "@lerna/package": "4.0.0", @@ -3903,47 +4447,10 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/symlink-binary/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/@lerna/symlink-binary/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/symlink-binary/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/symlink-dependencies": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-4.0.0.tgz", - "integrity": "sha512-BABo0MjeUHNAe2FNGty1eantWp8u83BHSeIMPDxNq0MuW2K3CiQRaeWT3EGPAzXpGt0+hVzBrA6+OT0GPn7Yuw==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/create-symlink": "4.0.0", "@lerna/resolve-symlink": "4.0.0", @@ -3956,67 +4463,18 @@ "node": ">= 10.18.0" } }, - "node_modules/@lerna/symlink-dependencies/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/@lerna/symlink-dependencies/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@lerna/symlink-dependencies/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@lerna/timer": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-4.0.0.tgz", - "integrity": "sha512-WFsnlaE7SdOvjuyd05oKt8Leg3ENHICnvX3uYKKdByA+S3g+TCz38JsNs7OUZVt+ba63nC2nbXDlUnuT2Xbsfg==", - "dev": true, - "engines": { - "node": ">= 10.18.0" - } - }, - "node_modules/@lerna/validation-error": { - "version": "3.13.0", "dev": true, "license": "MIT", - "dependencies": { - "npmlog": "^4.1.2" - }, "engines": { - "node": ">= 6.9.0" + "node": ">= 10.18.0" } }, "node_modules/@lerna/version": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/version/-/version-4.0.0.tgz", - "integrity": "sha512-otUgiqs5W9zGWJZSCCMRV/2Zm2A9q9JwSDS7s/tlKq4mWCYriWo7+wsHEA/nPTMDyYyBO5oyZDj+3X50KDUzeA==", "dev": true, + "license": "MIT", "dependencies": { "@lerna/check-working-tree": "4.0.0", "@lerna/child-process": "4.0.0", @@ -4051,9 +4509,8 @@ }, "node_modules/@lerna/version/node_modules/@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2" }, @@ -4063,9 +4520,8 @@ }, "node_modules/@lerna/version/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -4078,9 +4534,8 @@ }, "node_modules/@lerna/version/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4094,9 +4549,8 @@ }, "node_modules/@lerna/version/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -4106,36 +4560,32 @@ }, "node_modules/@lerna/version/node_modules/detect-indent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/version/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/version/node_modules/is-plain-obj": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/version/node_modules/load-json-file": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.15", "parse-json": "^5.0.0", @@ -4148,9 +4598,8 @@ }, "node_modules/@lerna/version/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -4158,35 +4607,10 @@ "node": ">=10" } }, - "node_modules/@lerna/version/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@lerna/version/node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@lerna/version/node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -4202,9 +4626,8 @@ }, "node_modules/@lerna/version/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4217,9 +4640,8 @@ }, "node_modules/@lerna/version/node_modules/sort-keys": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-obj": "^2.0.0" }, @@ -4232,18 +4654,16 @@ }, "node_modules/@lerna/version/node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/@lerna/version/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -4253,18 +4673,16 @@ }, "node_modules/@lerna/version/node_modules/type-fest": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/@lerna/version/node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -4274,9 +4692,8 @@ }, "node_modules/@lerna/version/node_modules/write-json-file": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^6.0.0", "graceful-fs": "^4.1.15", @@ -4294,15 +4711,13 @@ }, "node_modules/@lerna/version/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@lerna/write-log-file": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-4.0.0.tgz", - "integrity": "sha512-XRG5BloiArpXRakcnPHmEHJp+4AtnhRtpDIHSghmXD5EichI1uD73J7FgPp30mm2pDRq3FdqB0NbwSEsJ9xFQg==", "dev": true, + "license": "MIT", "dependencies": { "npmlog": "^4.1.2", "write-file-atomic": "^3.0.3" @@ -4313,9 +4728,8 @@ }, "node_modules/@lerna/write-log-file/node_modules/write-file-atomic": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -4323,44 +4737,223 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.9", + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": { + "version": "2.0.0", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/gauge": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": { + "version": "5.0.1", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.3.7", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, "node_modules/@microsoft/api-extractor": { - "version": "7.9.11", + "version": "7.20.1", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/api-extractor-model": "7.8.19", - "@microsoft/tsdoc": "0.12.19", - "@rushstack/node-core-library": "3.30.0", - "@rushstack/ts-command-line": "4.6.4", + "@microsoft/api-extractor-model": "7.16.0", + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.45.1", + "@rushstack/rig-package": "0.3.8", + "@rushstack/ts-command-line": "4.10.7", "colors": "~1.2.1", "lodash": "~4.17.15", "resolve": "~1.17.0", "semver": "~7.3.0", "source-map": "~0.6.1", - "typescript": "~3.9.5" + "typescript": "~4.5.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.8.19", + "version": "7.16.0", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.12.19", - "@rushstack/node-core-library": "3.30.0" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/resolve": { - "version": "1.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.45.1" } }, "node_modules/@microsoft/api-extractor/node_modules/semver": { @@ -4374,11 +4967,46 @@ "node": ">=10" } }, + "node_modules/@microsoft/api-extractor/node_modules/typescript": { + "version": "4.5.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@microsoft/tsdoc": { - "version": "0.12.19", + "version": "0.13.2", "dev": true, "license": "MIT" }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.15.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", "dev": true, @@ -4433,15 +5061,12 @@ }, "node_modules/@npmcli/ci-detect": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz", - "integrity": "sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/fs": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", - "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", - "dev": true, + "license": "ISC", "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -4449,9 +5074,7 @@ }, "node_modules/@npmcli/fs/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -4461,9 +5084,7 @@ }, "node_modules/@npmcli/fs/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4476,15 +5097,12 @@ }, "node_modules/@npmcli/fs/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "license": "ISC" }, "node_modules/@npmcli/git": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", - "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^1.3.2", "lru-cache": "^6.0.0", @@ -4498,9 +5116,8 @@ }, "node_modules/@npmcli/git/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -4510,9 +5127,8 @@ }, "node_modules/@npmcli/git/node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -4522,9 +5138,8 @@ }, "node_modules/@npmcli/git/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4537,9 +5152,8 @@ }, "node_modules/@npmcli/git/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4552,15 +5166,13 @@ }, "node_modules/@npmcli/git/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/installed-package-contents": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", "dev": true, + "license": "ISC", "dependencies": { "npm-bundled": "^1.1.1", "npm-normalize-package-bin": "^1.0.1" @@ -4574,9 +5186,7 @@ }, "node_modules/@npmcli/move-file": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -4587,9 +5197,7 @@ }, "node_modules/@npmcli/move-file/node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -4599,9 +5207,7 @@ }, "node_modules/@npmcli/move-file/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -4614,24 +5220,21 @@ }, "node_modules/@npmcli/node-gyp": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", - "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@npmcli/promise-spawn": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", - "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", "dev": true, + "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" } }, "node_modules/@npmcli/run-script": { "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.6.tgz", - "integrity": "sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g==", "dev": true, + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^1.0.2", "@npmcli/promise-spawn": "^1.3.2", @@ -4641,9 +5244,8 @@ }, "node_modules/@npmcli/run-script/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -4653,9 +5255,8 @@ }, "node_modules/@npmcli/run-script/node_modules/node-gyp": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", - "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -4677,9 +5278,8 @@ }, "node_modules/@npmcli/run-script/node_modules/nopt": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "1" }, @@ -4692,9 +5292,8 @@ }, "node_modules/@npmcli/run-script/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -4707,9 +5306,8 @@ }, "node_modules/@npmcli/run-script/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4722,9 +5320,8 @@ }, "node_modules/@npmcli/run-script/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4737,24 +5334,21 @@ }, "node_modules/@npmcli/run-script/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@octokit/auth-token": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^6.0.3" } }, "node_modules/@octokit/core": { "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", - "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/auth-token": "^2.4.4", "@octokit/graphql": "^4.5.8", @@ -4767,9 +5361,8 @@ }, "node_modules/@octokit/endpoint": { "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^6.0.3", "is-plain-object": "^5.0.0", @@ -4778,18 +5371,16 @@ }, "node_modules/@octokit/endpoint/node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/@octokit/graphql": { "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/request": "^5.6.0", "@octokit/types": "^6.0.3", @@ -4798,21 +5389,18 @@ }, "node_modules/@octokit/openapi-types": { "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", - "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^6.34.0" }, @@ -4822,18 +5410,16 @@ }, "node_modules/@octokit/plugin-request-log": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "dev": true, + "license": "MIT", "peerDependencies": { "@octokit/core": ">=3" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", - "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^6.34.0", "deprecation": "^2.3.1" @@ -4844,9 +5430,8 @@ }, "node_modules/@octokit/request": { "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz", - "integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.1.0", @@ -4858,9 +5443,8 @@ }, "node_modules/@octokit/request-error": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", @@ -4869,18 +5453,16 @@ }, "node_modules/@octokit/request/node_modules/is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/@octokit/rest": { "version": "18.12.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", - "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/core": "^3.5.1", "@octokit/plugin-paginate-rest": "^2.16.8", @@ -4890,202 +5472,24 @@ }, "node_modules/@octokit/types": { "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^11.2.0" } }, "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo": { - "version": "1.0.3", + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "@lerna/project": "~3.21.0" + "@lerna/project": "^4.0.0" }, "bin": { "api-extractor-lerna-monorepo": "cli.js" }, "peerDependencies": { - "typescript": "^3.7.0" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/@lerna/package": { - "version": "3.16.0", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^5.3.0", - "npm-package-arg": "^6.1.0", - "write-pkg": "^3.1.0" - }, - "engines": { - "node": ">= 6.9.0" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/@lerna/project": { - "version": "3.21.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/package": "3.16.0", - "@lerna/validation-error": "3.13.0", - "cosmiconfig": "^5.1.0", - "dedent": "^0.7.0", - "dot-prop": "^4.2.0", - "glob-parent": "^5.0.0", - "globby": "^9.2.0", - "load-json-file": "^5.3.0", - "npmlog": "^4.1.2", - "p-map": "^2.1.0", - "resolve-from": "^4.0.0", - "write-json-file": "^3.2.0" - }, - "engines": { - "node": ">= 6.9.0" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/dir-glob": { - "version": "2.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/globby": { - "version": "9.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/ignore": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/is-glob": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/load-json-file": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/make-dir": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/p-map": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/pify": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/slash": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/type-fest": { - "version": "0.3.1", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=6" - } - }, - "node_modules/@pixi-build-tools/api-extractor-lerna-monorepo/node_modules/write-json-file": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "engines": { - "node": ">=6" + "typescript": "^4.0.0" } }, "node_modules/@pixi/accessibility": { @@ -5096,48 +5500,52 @@ "resolved": "packages/app", "link": true }, + "node_modules/@pixi/assets": { + "resolved": "packages/assets", + "link": true + }, "node_modules/@pixi/basis": { "resolved": "packages/basis", "link": true }, "node_modules/@pixi/canvas-display": { - "resolved": "packages/canvas/canvas-display", + "resolved": "packages/canvas-display", "link": true }, "node_modules/@pixi/canvas-extract": { - "resolved": "packages/canvas/canvas-extract", + "resolved": "packages/canvas-extract", "link": true }, "node_modules/@pixi/canvas-graphics": { - "resolved": "packages/canvas/canvas-graphics", + "resolved": "packages/canvas-graphics", "link": true }, "node_modules/@pixi/canvas-mesh": { - "resolved": "packages/canvas/canvas-mesh", + "resolved": "packages/canvas-mesh", "link": true }, "node_modules/@pixi/canvas-particle-container": { - "resolved": "packages/canvas/canvas-particle-container", + "resolved": "packages/canvas-particle-container", "link": true }, "node_modules/@pixi/canvas-prepare": { - "resolved": "packages/canvas/canvas-prepare", + "resolved": "packages/canvas-prepare", "link": true }, "node_modules/@pixi/canvas-renderer": { - "resolved": "packages/canvas/canvas-renderer", + "resolved": "packages/canvas-renderer", "link": true }, "node_modules/@pixi/canvas-sprite": { - "resolved": "packages/canvas/canvas-sprite", + "resolved": "packages/canvas-sprite", "link": true }, "node_modules/@pixi/canvas-sprite-tiling": { - "resolved": "packages/canvas/canvas-sprite-tiling", + "resolved": "packages/canvas-sprite-tiling", "link": true }, "node_modules/@pixi/canvas-text": { - "resolved": "packages/canvas/canvas-text", + "resolved": "packages/canvas-text", "link": true }, "node_modules/@pixi/compressed-textures": { @@ -5157,12 +5565,12 @@ "link": true }, "node_modules/@pixi/eslint-config": { - "version": "2.0.1", + "version": "4.0.1", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0", - "@typescript-eslint/parser": "^4.0.0" + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0" }, "peerDependencies": { "eslint": ">=7.0.0", @@ -5173,32 +5581,36 @@ "resolved": "packages/events", "link": true }, + "node_modules/@pixi/extensions": { + "resolved": "packages/extensions", + "link": true + }, "node_modules/@pixi/extract": { "resolved": "packages/extract", "link": true }, "node_modules/@pixi/filter-alpha": { - "resolved": "packages/filters/filter-alpha", + "resolved": "packages/filter-alpha", "link": true }, "node_modules/@pixi/filter-blur": { - "resolved": "packages/filters/filter-blur", + "resolved": "packages/filter-blur", "link": true }, "node_modules/@pixi/filter-color-matrix": { - "resolved": "packages/filters/filter-color-matrix", + "resolved": "packages/filter-color-matrix", "link": true }, "node_modules/@pixi/filter-displacement": { - "resolved": "packages/filters/filter-displacement", + "resolved": "packages/filter-displacement", "link": true }, "node_modules/@pixi/filter-fxaa": { - "resolved": "packages/filters/filter-fxaa", + "resolved": "packages/filter-fxaa", "link": true }, "node_modules/@pixi/filter-noise": { - "resolved": "packages/filters/filter-noise", + "resolved": "packages/filter-noise", "link": true }, "node_modules/@pixi/graphics": { @@ -5209,14 +5621,6 @@ "resolved": "packages/graphics-extras", "link": true }, - "node_modules/@pixi/interaction": { - "resolved": "packages/interaction", - "link": true - }, - "node_modules/@pixi/loaders": { - "resolved": "packages/loaders", - "link": true - }, "node_modules/@pixi/math": { "resolved": "packages/math", "link": true @@ -5245,12 +5649,12 @@ "resolved": "packages/mixin-get-global-position", "link": true }, - "node_modules/@pixi/particle-container": { - "resolved": "packages/particle-container", + "node_modules/@pixi/node": { + "resolved": "bundles/pixi.js-node", "link": true }, - "node_modules/@pixi/polyfill": { - "resolved": "packages/polyfill", + "node_modules/@pixi/particle-container": { + "resolved": "packages/particle-container", "link": true }, "node_modules/@pixi/prepare": { @@ -5303,9 +5707,8 @@ }, "node_modules/@pixi/webdoc-template": { "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@pixi/webdoc-template/-/webdoc-template-1.5.3.tgz", - "integrity": "sha512-Q988OAvg0NsfoSE6Bl99Lej1l4O1QgV09ZWAnDDKi7FDSGxhY+sQpenN4DEmB27rzW5RJiST3irnTKq1S5TnKg==", "dev": true, + "license": "MIT", "dependencies": { "code-prettify": "^0.1.0", "color-themes-for-google-code-prettify": "^2.0.4", @@ -5319,50 +5722,11 @@ "open-sans-fonts": "^1.6.2", "taffydb": "^2.7.3" }, - "engines": { - "node": ">= 12", - "npm": ">= 6", - "pnpm": "please-use-npm", - "yarn": "please-use-npm" - }, "peerDependencies": { "@webdoc/model": "^1.2.1", "@webdoc/template-library": "^1.2.1" } }, - "node_modules/@pixi/webdoc-template/node_modules/fs-extra": { - "version": "9.1.0", - "dev": true, - "license": "MIT", - "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/@pixi/webdoc-template/node_modules/jsonfile": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@pixi/webdoc-template/node_modules/universalify": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@rollup/plugin-alias": { "version": "3.1.1", "dev": true, @@ -5377,82 +5741,6 @@ "rollup": "^1.20.0||^2.0.0" } }, - "node_modules/@rollup/plugin-buble": { - "version": "0.21.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^3.0.8", - "@types/buble": "^0.19.2", - "buble": "^0.20.0" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/plugin-buble/node_modules/buble": { - "version": "0.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^6.4.1", - "acorn-dynamic-import": "^4.0.0", - "acorn-jsx": "^5.2.0", - "chalk": "^2.4.2", - "magic-string": "^0.25.7", - "minimist": "^1.2.5", - "regexpu-core": "4.5.4" - }, - "bin": { - "buble": "bin/buble" - } - }, - "node_modules/@rollup/plugin-buble/node_modules/magic-string": { - "version": "0.25.7", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/@rollup/plugin-buble/node_modules/regenerate-unicode-properties": { - "version": "8.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@rollup/plugin-buble/node_modules/regexpu-core": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@rollup/plugin-buble/node_modules/unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/@rollup/plugin-commonjs": { "version": "15.1.0", "dev": true, @@ -5536,14 +5824,6 @@ "@types/node": "*" } }, - "node_modules/@rollup/plugin-node-resolve/node_modules/deepmerge": { - "version": "4.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@rollup/plugin-node-resolve/node_modules/resolve": { "version": "1.18.1", "dev": true, @@ -5556,35 +5836,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@rollup/plugin-typescript": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "rollup": "^2.14.0", - "tslib": "*", - "typescript": ">=3.4.0" - } - }, - "node_modules/@rollup/plugin-typescript/node_modules/resolve": { - "version": "1.18.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@rollup/pluginutils": { "version": "3.1.0", "dev": true, @@ -5612,11 +5863,11 @@ "license": "MIT" }, "node_modules/@rushstack/node-core-library": { - "version": "3.30.0", + "version": "3.45.1", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "10.17.13", + "@types/node": "12.20.24", "colors": "~1.2.1", "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", @@ -5624,14 +5875,9 @@ "resolve": "~1.17.0", "semver": "~7.3.0", "timsort": "~0.3.0", - "z-schema": "~3.18.3" + "z-schema": "~5.0.2" } }, - "node_modules/@rushstack/node-core-library/node_modules/@types/node": { - "version": "10.17.13", - "dev": true, - "license": "MIT" - }, "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { "version": "7.0.1", "dev": true, @@ -5645,30 +5891,39 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/@rushstack/node-core-library/node_modules/resolve": { - "version": "1.17.0", + "node_modules/@rushstack/node-core-library/node_modules/lru-cache": { + "version": "7.8.0", "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/@rushstack/node-core-library/node_modules/semver": { - "version": "7.3.2", + "version": "7.3.6", "dev": true, "license": "ISC", + "dependencies": { + "lru-cache": "^7.4.0" + }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@rushstack/rig-package": { + "version": "0.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "~1.17.0", + "strip-json-comments": "~3.1.1" } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.6.4", + "version": "4.10.7", "dev": true, "license": "MIT", "dependencies": { @@ -5678,45 +5933,116 @@ "string-argv": "~0.3.1" } }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", + "node_modules/@sentry/core": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.2.0.tgz", + "integrity": "sha512-9amsbB9/ePkJRgc0cVXCVW2hQUPImgTqBbnKu4frBXBza+9MBC5W3S8ZyZt2InCK22kuhNVo3z61a8mzCgXoCA==", "dev": true, - "license": "MIT", + "dependencies": { + "@sentry/hub": "7.2.0", + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "tslib": "^1.9.3" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@sinonjs/commons": { - "version": "1.4.0", + "node_modules/@sentry/hub": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.2.0.tgz", + "integrity": "sha512-uzd+GzD++Z4QopRh3AyRc4jz4AzomMnrXTOmdXgud1BH/Du9AYutVlBc5ZYwqCuJH7QPuAW3ySU3P+16UCinIg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "type-detect": "4.0.8" + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@sinonjs/formatio": { - "version": "3.2.1", + "node_modules/@sentry/integrations": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.2.0.tgz", + "integrity": "sha512-plOD3tTEUqLpu/VNo5bE4ojSm86sYPk6PPxIBQKfKUNOMpJGSqxsLOJesVz5v/jcIW/CYXuMTHqgculovr7t/Q==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "localforage": "^1.8.1", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@sinonjs/samsam": { - "version": "3.3.2", + "node_modules/@sentry/node": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.2.0.tgz", + "integrity": "sha512-dSI+2DrT98+eqSAv3QG3jMrq4YefBaxRbSCR9Ok7oLQW2/eskbRWH4mgYssrDXEx319SBYHh90qq/EwCOEkHtw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^1.0.2", - "array-from": "^2.1.1", - "lodash": "^4.17.11" + "@sentry/core": "7.2.0", + "@sentry/hub": "7.2.0", + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", + "node_modules/@sentry/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.2.0.tgz", + "integrity": "sha512-e6w62C2AmE5ULr9w/BuVaKTRpKUMGWyw4PhcBlSdDRoS47QgURGgDFIvr3VlaDwkUfCbASwSv49fDhKRX3aoew==", "dev": true, - "license": "(Unlicense OR Apache-2.0)" + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/utils": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-uUKIsIXyb6ZXBbl/L8UwG4gy8PBXZl5pGCUFRPbns+vi0U6vtmDRDYa1A/7E17VkBJNRPVNJQr9Pq5Yd0I0MRA==", + "dev": true, + "dependencies": { + "@sentry/types": "7.2.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } }, "node_modules/@szmarczak/http-timer": { "version": "1.1.2", @@ -5731,9 +6057,7 @@ }, "node_modules/@tootallnate/once": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -5743,12 +6067,45 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/buble": { - "version": "0.19.2", + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", "dev": true, - "license": "MIT", "dependencies": { - "magic-string": "^0.25.0" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.3.0" } }, "node_modules/@types/color-name": { @@ -5756,6 +6113,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "dev": true + }, "node_modules/@types/earcut": { "version": "2.1.1", "license": "MIT" @@ -5765,6 +6128,10 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/gl": { + "version": "4.1.0", + "license": "MIT" + }, "node_modules/@types/glob": { "version": "7.1.3", "dev": true, @@ -5774,8 +6141,51 @@ "@types/node": "*" } }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "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": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, + "dependencies": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, "node_modules/@types/json-schema": { - "version": "7.0.6", + "version": "7.0.11", "dev": true, "license": "MIT" }, @@ -5786,18 +6196,11 @@ }, "node_modules/@types/minimist": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "8.2.3", "dev": true, "license": "MIT" }, "node_modules/@types/node": { - "version": "12.7.5", - "dev": true, + "version": "12.20.24", "license": "MIT" }, "node_modules/@types/normalize-package-data": { @@ -5805,50 +6208,74 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/object-assign": { - "version": "4.0.30", - "dev": true, - "license": "MIT" - }, "node_modules/@types/offscreencanvas": { "version": "2019.6.4", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", - "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + "license": "MIT" }, "node_modules/@types/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", "dev": true }, - "node_modules/@types/promise-polyfill": { - "version": "6.0.3", + "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/xml2js": { + "version": "0.4.11", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", "dev": true, - "license": "MIT" + "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/@typescript-eslint/eslint-plugin": { - "version": "4.12.0", + "version": "5.23.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/experimental-utils": "4.12.0", - "@typescript-eslint/scope-manager": "4.12.0", - "debug": "^4.1.1", + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/type-utils": "5.23.0", + "@typescript-eslint/utils": "5.23.0", + "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -5857,7 +6284,7 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", "dev": true, "license": "MIT", "dependencies": { @@ -5889,7 +6316,7 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.4", + "version": "7.3.7", "dev": true, "license": "ISC", "dependencies": { @@ -5907,48 +6334,25 @@ "dev": true, "license": "ISC" }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.12.0", - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/typescript-estree": "4.12.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "4.12.0", + "version": "5.23.0", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "4.12.0", - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/typescript-estree": "4.12.0", - "debug": "^4.1.1" + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/typescript-estree": "5.23.0", + "debug": "^4.3.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -5957,7 +6361,7 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", "dev": true, "license": "MIT", "dependencies": { @@ -5978,27 +6382,73 @@ "license": "MIT" }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.12.0", + "version": "5.23.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/visitor-keys": "5.23.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.23.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/visitor-keys": "4.12.0" + "@typescript-eslint/utils": "5.23.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" }, "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/types": { - "version": "4.12.0", + "version": "5.23.0", "dev": true, "license": "MIT", "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -6006,21 +6456,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.12.0", + "version": "5.23.0", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/visitor-keys": "4.12.0", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/visitor-keys": "5.23.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", @@ -6033,7 +6482,7 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.1", + "version": "4.3.4", "dev": true, "license": "MIT", "dependencies": { @@ -6049,7 +6498,7 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/is-glob": { - "version": "4.0.1", + "version": "4.0.3", "dev": true, "license": "MIT", "dependencies": { @@ -6076,7 +6525,7 @@ "license": "MIT" }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.4", + "version": "7.3.7", "dev": true, "license": "ISC", "dependencies": { @@ -6094,60 +6543,111 @@ "dev": true, "license": "ISC" }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.12.0", + "node_modules/@typescript-eslint/utils": { + "version": "5.23.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "4.12.0", - "eslint-visitor-keys": "^2.0.0" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/typescript-estree": "5.23.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "2.0.0", + "node_modules/@typescript-eslint/utils/node_modules/eslint-utils": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=10" } }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.23.0", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.23.0", + "eslint-visitor-keys": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, "node_modules/@webdoc/cli": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/cli/-/cli-1.5.5.tgz", - "integrity": "sha512-RbC3BzwGKHn1r+zoWRBqtGFb5tJEG9/IkZoDKUlgSO7h5MkSl2HKj9/vmW2giv8MdoiZnF7WRDWwSDkWcdDunA==", - "dev": true, - "dependencies": { - "@webdoc/default-template": "^1.5.5", - "@webdoc/externalize": "^1.5.5", - "@webdoc/legacy-template": "^1.5.5", - "@webdoc/model": "^1.5.5", - "@webdoc/parser": "^1.5.5", - "@webdoc/plugin-markdown": "^1.5.5", - "@webdoc/template-library": "^1.5.5", - "@webdoc/types": "^1.5.5", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/cli/-/cli-2.0.0.tgz", + "integrity": "sha512-ajf4gOeiEFjqFCuAVsBRj5W25LZiMAYGTQLQhzWRbiIa/gh9aUWQqWcf6l2gS0pF58U0bSuuWoQSsV5XF/t10w==", + "dev": true, + "dependencies": { + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@sentry/integrations": "7.2.0", + "@sentry/node": "7.2.0", + "@webdoc/default-template": "^2.0.0", + "@webdoc/externalize": "^2.0.0", + "@webdoc/language-babel": "^2.0.0", + "@webdoc/language-parser": "^2.0.0", + "@webdoc/legacy-template": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/plugin-markdown": "^2.0.0", + "@webdoc/template-library": "^2.0.0", + "@webdoc/types": "^2.0.0", "array.prototype.flatmap": "~1.2.3", "fs-extra": "^9.0.1", "globby": "11.0.0", + "gunzip-maybe": "1.4.2", + "highlight.js": "~10.7.2", + "inquirer": "9.0.0", "lodash.merge": "4.6.2", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0", + "markdown-it": "13.0.1", "missionlog": "1.6.0", "object.fromentries": "^2.0.2", "perf_hooks": "~0.0.1", "pkg-up": "~3.1.0", "read-pkg-up": "~7.0.1", + "tar-stream": "2.2.0", "yargs": "^16.2.0" }, "bin": { @@ -6162,6 +6662,33 @@ "node": ">= 8" } }, + "node_modules/@webdoc/cli/node_modules/ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@webdoc/cli/node_modules/ansi-escapes/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@webdoc/cli/node_modules/ansi-regex": { "version": "5.0.0", "dev": true, @@ -6184,6 +6711,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/@webdoc/cli/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/@webdoc/cli/node_modules/array-union": { "version": "2.1.0", "dev": true, @@ -6203,6 +6736,42 @@ "node": ">=8" } }, + "node_modules/@webdoc/cli/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@webdoc/cli/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@webdoc/cli/node_modules/cli-width": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", + "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/@webdoc/cli/node_modules/cliui": { "version": "7.0.4", "dev": true, @@ -6229,6 +6798,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@webdoc/cli/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@webdoc/cli/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@webdoc/cli/node_modules/fast-glob": { "version": "3.2.5", "dev": true, @@ -6245,29 +6838,31 @@ "node": ">=8" } }, - "node_modules/@webdoc/cli/node_modules/fill-range": { - "version": "7.0.1", + "node_modules/@webdoc/cli/node_modules/figures": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", + "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", "dev": true, - "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@webdoc/cli/node_modules/fs-extra": { - "version": "9.1.0", + "node_modules/@webdoc/cli/node_modules/fill-range": { + "version": "7.0.1", "dev": true, "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, "node_modules/@webdoc/cli/node_modules/get-caller-file": { @@ -6308,6 +6903,111 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@webdoc/cli/node_modules/inquirer": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.0.0.tgz", + "integrity": "sha512-eYTDdTYr/YPwRenOzLZTvaJUDXDW8GQgxvzBppuXLj/kauTRLfV8bCPVbGh2staP7edrqL+rGwjaOa+JVxBWsg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^5.0.0", + "chalk": "^5.0.1", + "cli-cursor": "^4.0.0", + "cli-width": "^4.0.0", + "external-editor": "^3.0.3", + "figures": "^4.0.1", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^6.1.0", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^5.1.2", + "strip-ansi": "^7.0.1", + "through": "^2.3.6", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@webdoc/cli/node_modules/inquirer/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": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@webdoc/cli/node_modules/inquirer/node_modules/ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@webdoc/cli/node_modules/inquirer/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/@webdoc/cli/node_modules/inquirer/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, + "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_modules/@webdoc/cli/node_modules/inquirer/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@webdoc/cli/node_modules/inquirer/node_modules/wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@webdoc/cli/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, @@ -6335,15 +7035,29 @@ "node": ">=0.12.0" } }, - "node_modules/@webdoc/cli/node_modules/jsonfile": { - "version": "6.1.0", + "node_modules/@webdoc/cli/node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, - "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "uc.micro": "^1.0.1" + } + }, + "node_modules/@webdoc/cli/node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, "node_modules/@webdoc/cli/node_modules/micromatch": { @@ -6413,6 +7127,31 @@ "node": ">=8" } }, + "node_modules/@webdoc/cli/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@webdoc/cli/node_modules/rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/@webdoc/cli/node_modules/string-width": { "version": "4.2.0", "dev": true, @@ -6448,13 +7187,11 @@ "node": ">=8.0" } }, - "node_modules/@webdoc/cli/node_modules/universalify": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } + "node_modules/@webdoc/cli/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true }, "node_modules/@webdoc/cli/node_modules/wrap-ansi": { "version": "7.0.0", @@ -6506,79 +7243,185 @@ } }, "node_modules/@webdoc/default-template": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/default-template/-/default-template-1.5.5.tgz", - "integrity": "sha512-5XeHVYqUL2Mrm/bSImg3OAnAkeXMxANRPgRroHj6Aty7kkcSYOwN37Ns/oPsGKWeU5BJvxZO7Y0+Zzs7J9X/gw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/default-template/-/default-template-2.0.0.tgz", + "integrity": "sha512-Uo8hibY6lXvw53qdlId9gY2bXWLPKSP1Kff+3uBCjdWICzH34ZIjYvNwWOZjIzroI230iHKS5HY/ythiVfNaiQ==", "dev": true, "dependencies": { - "@babel/core": "^7.9.0", + "@babel/core": "7.18.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", "@babel/preset-react": "^7.10.1", - "@webdoc/model": "^1.5.5", - "@webdoc/template-library": "^1.5.5", - "@webdoc/types": "^1.5.5", + "@webdoc/model": "^2.0.0", + "@webdoc/template-library": "^2.0.0", + "@webdoc/types": "^2.0.0", "code-prettify": "^0.1.0", "fs-extra": "^9.0.1", "highlight.js": "~10.7.2", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0" + "markdown-it": "13.0.1" } }, - "node_modules/@webdoc/default-template/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/@webdoc/default-template/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@webdoc/default-template/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@webdoc/default-template/node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "uc.micro": "^1.0.1" + } + }, + "node_modules/@webdoc/default-template/node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "engines": { - "node": ">=10" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "node_modules/@webdoc/default-template/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@webdoc/externalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/externalize/-/externalize-2.0.0.tgz", + "integrity": "sha512-q47axWF396LI8VCwtKP/Ao2M2q6UGeiSiLoErwulCJiPUJRKgE0kO9caOeydGWfxPiELvKRACJ3Bg2VVqmLgPg==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "@babel/core": "7.18.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20" + } + }, + "node_modules/@webdoc/language-babel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/language-babel/-/language-babel-2.0.0.tgz", + "integrity": "sha512-IxUZlZ0pJJ0yuUMpF5WAjabHzWXX7aDhXbOC0KkZiVyDkzgqjeK1q/Ao7nqlYQlhHewYlbIM50ShX0fAGYFMLg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/language-library": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "peerDependencies": { + "@sentry/node": "7.2.0" + } + }, + "node_modules/@webdoc/language-babel/node_modules/@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, - "node_modules/@webdoc/default-template/node_modules/universalify": { + "node_modules/@webdoc/language-library": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "resolved": "https://registry.npmjs.org/@webdoc/language-library/-/language-library-2.0.0.tgz", + "integrity": "sha512-btV+hhSlO0EvPMRFrBHepp1ayQEvgKxJJu9RkF3CsTI1D8/BGr5cja0+Q+ndNXWKvTDVzpG68o3uGwQg4NdujA==", "dev": true, - "engines": { - "node": ">= 10.0.0" + "dependencies": { + "@babel/parser": "^7.9.4", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" + }, + "peerDependencies": { + "@sentry/node": "7.2.0" } }, - "node_modules/@webdoc/externalize": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/externalize/-/externalize-1.5.5.tgz", - "integrity": "sha512-cvDpVd4nX+n6vAwgabt5QXVXxPBKvat5CsydHwdErww/XTDRCZzy3sbCtzGBwyd4ZNrx3aSl4nJSAJjwf/WsUQ==", + "node_modules/@webdoc/language-library/node_modules/@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", "dev": true, "dependencies": { - "@babel/core": "^7.9.0", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", - "lodash": "^4.17.20" + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@webdoc/language-parser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/language-parser/-/language-parser-2.0.0.tgz", + "integrity": "sha512-vZUcqILH2Itgq/rF02FqrMlJcTNi+k9Vj2sxURXFlhvmPKa+jx4ErfPdrrHGxI+TbUPVinRgVZzECuuOSP4P1g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/language-library": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" + }, + "peerDependencies": { + "@sentry/node": "7.2.0" + } + }, + "node_modules/@webdoc/language-parser/node_modules/@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } }, "node_modules/@webdoc/legacy-template": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/legacy-template/-/legacy-template-1.5.5.tgz", - "integrity": "sha512-Pvx1WwOMGjFNbd24T9LEqB8traj3DP75GUFweQ2vL2hyHg3hS7fpDsTttw7ePlm1usylhZFvJ37AgCID9a5WcA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/legacy-template/-/legacy-template-2.0.0.tgz", + "integrity": "sha512-aNGS8HFm2gAkOEY4rxNaYLj5Fo/pVVPG8Gu+noN3AuzyCKBkLeqWZzbeJr5WElhIUvzekBiy7/D/S7TSPaKLDg==", "dev": true, "dependencies": { - "@webdoc/model": "^1.5.5", - "@webdoc/template-library": "^1.5.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/model": "^2.0.0", + "@webdoc/template-library": "^2.0.0", "bluebird": "^3.7.2", "code-prettify": "^0.1.0", "color-themes-for-google-code-prettify": "^2.0.4", @@ -6587,13 +7430,30 @@ "fs-extra": "^9.0.1", "klaw-sync": "6.0.0", "lodash": "^4.17.20", - "markdown-it": "^11.0.0", + "markdown-it": "13.0.1", "markdown-it-highlightjs": "^3.1.0", - "marked": "^0.8.2", "missionlog": "1.6.0", "open-sans-fonts": "^1.6.2" } }, + "node_modules/@webdoc/legacy-template/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@webdoc/legacy-template/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/@webdoc/legacy-template/node_modules/escape-string-regexp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-3.0.0.tgz", @@ -6606,103 +7466,114 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@webdoc/legacy-template/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/@webdoc/legacy-template/node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "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" + "uc.micro": "^1.0.1" } }, - "node_modules/@webdoc/legacy-template/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@webdoc/legacy-template/node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@webdoc/legacy-template/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, "node_modules/@webdoc/model": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/model/-/model-1.5.5.tgz", - "integrity": "sha512-fqFXe9VbtcooAkZGOD8hilux86FQKhnD2KQCXxbS/sip50WbZGegHWnJrYQIH9FwXbXuTENw7ztc8LsMY2pkMQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/model/-/model-2.0.0.tgz", + "integrity": "sha512-OtyW4kigvXN9JaqAOh8S1zbRP1K1eEKP5WEi12eGfKQNmZNWhyMLxlriEbaGneX8hQWaM2uM2FMo5+nEl3oHmg==", "dev": true, "dependencies": { - "@webdoc/types": "^1.5.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/types": "^2.0.0", "catharsis": "0.8.11", "nanoid": "~3.1.16", "taffydb": "2.7.3" } }, - "node_modules/@webdoc/parser": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/parser/-/parser-1.5.5.tgz", - "integrity": "sha512-Fpow4bMSSkBY52r57mnn3fuVREcc1rOoWdRxQcI/BjDfiAXz3xa7gH1xbXvxIE5LatN5dgRbYU81ILhCl18RvA==", + "node_modules/@webdoc/plugin-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/plugin-markdown/-/plugin-markdown-2.0.0.tgz", + "integrity": "sha512-bxbVpj7HSoUocj65FeU54DgL3mbzA0S2ird5LknOqO1gfQYn2ESVw46mwgeVyGZ46+nxWEMi6/53MOJbouor1Q==", "dev": true, "dependencies": { - "@babel/parser": "^7.9.4", - "@babel/traverse": "7.9.5", - "@babel/types": "7.9.5", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", - "lodash": "^4.17.20", - "missionlog": "1.6.0", - "nanoid": "~3.1.16" + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "highlight.js": "~10.7.2", + "markdown-it": "13.0.1" } }, - "node_modules/@webdoc/parser/node_modules/@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "node_modules/@webdoc/plugin-markdown/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@webdoc/plugin-markdown/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@webdoc/plugin-markdown/node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" + "uc.micro": "^1.0.1" } }, - "node_modules/@webdoc/plugin-markdown": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/plugin-markdown/-/plugin-markdown-1.5.5.tgz", - "integrity": "sha512-Mzu/stCH9eqOA4yyKE42k8EwIW3TQyj3euxc14Ohw/PVMC2Uk97u6JEiVQAuBSoi0vHp27rNVTICCtdLKxQFnQ==", + "node_modules/@webdoc/plugin-markdown/node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", "dev": true, "dependencies": { - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0" + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" } }, "node_modules/@webdoc/template-library": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/template-library/-/template-library-1.5.5.tgz", - "integrity": "sha512-nyNzLPj3g09bFdFNKEnNw0xxm1zy3+bdW17dhTREWKBgLQ7z7XrZeHTOI/jJ2zh4RFOIGExyYTx4nZ/luPhFEg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/template-library/-/template-library-2.0.0.tgz", + "integrity": "sha512-71lmtpsQXPLXeyggWM9yCoGP8LkXVyLyGlnMclgsEXGTZWyeueg+GlwbUGPuJWW9WSSQS1KKevbDSapQwpt9rQ==", "dev": true, "dependencies": { - "@webdoc/externalize": "^1.5.5", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@fork-of/git-branch": "2.1.1", + "@webdoc/externalize": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", "catharsis": "0.8.11", "fs-extra": "^9.0.1", - "git-branch": "2.0.1", "lodash": "^4.17.20", "missionlog": "1.6.0", "nanoid": "~3.1.16", @@ -6710,55 +7581,40 @@ "parse-github-url": "1.0.2" } }, - "node_modules/@webdoc/template-library/node_modules/fs-extra": { - "version": "9.1.0", - "dev": true, - "license": "MIT", - "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/@webdoc/template-library/node_modules/jsonfile": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@webdoc/template-library/node_modules/universalify": { + "node_modules/@webdoc/types": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/types/-/types-2.0.0.tgz", + "integrity": "sha512-QfyP46Et1PXk8Bb6IAEX8EuGbSJXPKFsP43866Dt+TW+FiTnvnU8ISQGyMPFNfmGQuCii2CWZfcbttaye/xmFA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" + "dependencies": { + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12" } }, - "node_modules/@webdoc/types": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/types/-/types-1.5.5.tgz", - "integrity": "sha512-XTHsivrEgjSmZM4M6KbdNyJ859et6ifEgKy7TfLMAYbpgpZx7bOagSdKB33S7YICTaxxBFrlPeklGJKfFB6lNg==", + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, "node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "license": "ISC" }, - "node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -6767,14 +7623,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-dynamic-import": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0" - } - }, "node_modules/acorn-jsx": { "version": "5.2.0", "dev": true, @@ -6783,17 +7631,23 @@ "acorn": "^6.0.0 || ^7.0.0" } }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/add-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "license": "MIT", "dependencies": { "debug": "4" }, @@ -6803,9 +7657,7 @@ }, "node_modules/agent-base/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -6820,15 +7672,11 @@ }, "node_modules/agent-base/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "license": "MIT" }, "node_modules/agentkeepalive": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", - "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", - "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.1.0", "depd": "^1.1.2", @@ -6840,9 +7688,7 @@ }, "node_modules/agentkeepalive/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -6857,13 +7703,10 @@ }, "node_modules/agentkeepalive/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "license": "MIT" }, "node_modules/aggregate-error": { "version": "3.1.0", - "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -6875,9 +7718,8 @@ }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6889,19 +7731,10 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -6914,9 +7747,8 @@ }, "node_modules/ansi-escapes/node_modules/type-fest": { "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -6926,7 +7758,6 @@ }, "node_modules/ansi-regex": { "version": "2.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6955,27 +7786,10 @@ "node": ">= 8" } }, - "node_modules/append-transform": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/aproba": { "version": "1.2.0", - "dev": true, "license": "ISC" }, - "node_modules/archy": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/are-we-there-yet": { "version": "1.1.5", "dev": true, @@ -7043,29 +7857,27 @@ }, "node_modules/array-differ": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/array-from": { - "version": "2.1.1", - "dev": true, - "license": "MIT" + "node_modules/array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "dev": true }, "node_modules/array-ify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/array-includes": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3", @@ -7134,34 +7946,23 @@ }, "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/asn1": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } }, "node_modules/assert-plus": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", "dev": true, "license": "MIT", "engines": { - "node": "*" + "node": ">=0.8" } }, "node_modules/assign-symbols": { @@ -7180,11 +7981,25 @@ "node": ">=4" } }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -7207,22 +8022,200 @@ }, "node_modules/aws-sign2": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/aws4": { "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/babel-jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", + "dev": true, + "dependencies": { + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-jest/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/babel-jest/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/babel-jest/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/babel-jest/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/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "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.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "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": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": ">= 10.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, "node_modules/balanced-match": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/base": { @@ -7296,33 +8289,112 @@ "node": ">=0.10.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==", + "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/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/before-after-hook": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bindings": { + "version": "1.5.0", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bit-twiddle": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" } }, "node_modules/bluebird": { "version": "3.7.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true }, "node_modules/boolean": { "version": "3.0.2", @@ -7332,7 +8404,6 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -7370,31 +8441,105 @@ "node": ">=0.10.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, - "license": "ISC" + "dependencies": { + "resolve": "1.1.7" + } + }, + "node_modules/browser-resolve/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true + }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } }, "node_modules/browserslist": { - "version": "4.16.6", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", + "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "dependencies": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "caniuse-lite": "^1.0.30001366", + "electron-to-chromium": "^1.4.188", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.4" }, "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" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "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", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-crc32": { @@ -7425,27 +8570,23 @@ }, "node_modules/byline": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/byte-size": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz", - "integrity": "sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/cacache": { "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, + "license": "ISC", "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -7472,9 +8613,7 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -7484,9 +8623,7 @@ }, "node_modules/cacache/node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -7496,9 +8633,7 @@ }, "node_modules/cacache/node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -7511,9 +8646,7 @@ }, "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "license": "ISC" }, "node_modules/cache-base": { "version": "1.0.1", @@ -7581,53 +8714,6 @@ "node": ">=8" } }, - "node_modules/caching-transform": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/caching-transform/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caching-transform/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/caching-transform/node_modules/write-file-atomic": { - "version": "3.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "node_modules/call-bind": { "version": "1.0.2", "dev": true, @@ -7645,50 +8731,27 @@ "dev": true, "license": "MIT" }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/callsites": { - "version": "2.0.0", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase-keys": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, + "license": "MIT", "dependencies": { "camelcase": "^5.3.1", "map-obj": "^4.0.0", @@ -7703,9 +8766,8 @@ }, "node_modules/camelcase-keys/node_modules/map-obj": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -7714,174 +8776,111 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001222", - "dev": true, - "license": "CC-BY-4.0" - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/catharsis": { - "version": "0.8.11", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "version": "1.0.30001369", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001369.tgz", + "integrity": "sha512-OY1SBHaodJc4wflDIKnlkdqWzJZd1Ls/2zbVJHBSv3AT7vgOJ58yAhd2CN4d57l2kPJrgMb7P9+N1Mhy4tNSQA==", "dev": true, - "engines": { - "node": "*" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, - "node_modules/chokidar": { - "version": "3.5.1", - "dev": true, + "node_modules/canvas": { + "version": "2.9.1", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.15.0", + "simple-get": "^3.0.3" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" + "node": ">=6" } }, - "node_modules/chokidar/node_modules/braces": { - "version": "3.0.2", + "node_modules/capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", "dev": true, - "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "rsvp": "^4.8.4" }, "engines": { - "node": ">=8" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/chokidar/node_modules/fill-range": { - "version": "7.0.1", + "node_modules/caseless": { + "version": "0.12.0", "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } + "license": "Apache-2.0" }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", + "node_modules/catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", "dev": true, - "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "lodash": "^4.17.14" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, - "node_modules/chokidar/node_modules/is-glob": { - "version": "4.0.1", + "node_modules/chalk": { + "version": "2.4.2", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/chokidar/node_modules/is-number": { - "version": "7.0.0", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": ">=10" } }, - "node_modules/chokidar/node_modules/to-regex-range": { - "version": "5.0.1", + "node_modules/chardet": { + "version": "0.7.0", "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } + "license": "MIT" }, "node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/chunkd": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ci-info": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cjs-module-lexer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", + "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", "dev": true }, "node_modules/class-utils": { @@ -7919,7 +8918,6 @@ }, "node_modules/clean-stack": { "version": "2.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7927,9 +8925,8 @@ }, "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, + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -7937,11 +8934,22 @@ "node": ">=8" } }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-width": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, + "license": "ISC", "engines": { "node": ">= 10" } @@ -7997,18 +9005,16 @@ }, "node_modules/clone": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true, + "license": "MIT", "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, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -8020,9 +9026,8 @@ }, "node_modules/clone-deep/node_modules/kind-of": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8037,9 +9042,8 @@ }, "node_modules/cmd-shim": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz", - "integrity": "sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==", "dev": true, + "license": "ISC", "dependencies": { "mkdirp-infer-owner": "^2.0.0" }, @@ -8047,9 +9051,18 @@ "node": ">=10" } }, + "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/code-point-at": { "version": "1.1.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8060,6 +9073,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, "node_modules/collection-visit": { "version": "1.0.0", "dev": true, @@ -8085,6 +9104,13 @@ "dev": true, "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/color-themes-for-google-code-prettify": { "version": "2.0.4", "dev": true, @@ -8093,11 +9119,6 @@ "node": ">=5.9.0" } }, - "node_modules/colorette": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, "node_modules/colors": { "version": "1.2.5", "dev": true, @@ -8108,9 +9129,8 @@ }, "node_modules/columnify": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", "dev": true, + "license": "MIT", "dependencies": { "strip-ansi": "^3.0.0", "wcwidth": "^1.0.0" @@ -8118,9 +9138,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8130,9 +9149,17 @@ }, "node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/comment-parser": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } }, "node_modules/common-path-prefix": { "version": "3.0.0", @@ -8146,9 +9173,8 @@ }, "node_modules/compare-func": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, + "license": "MIT", "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" @@ -8156,9 +9182,8 @@ }, "node_modules/compare-func/node_modules/dot-prop": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, + "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, @@ -8168,9 +9193,8 @@ }, "node_modules/compare-func/node_modules/is-obj": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8182,7 +9206,6 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "dev": true, "license": "MIT" }, "node_modules/concat-stream": { @@ -8235,14 +9258,12 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "dev": true, "license": "ISC" }, "node_modules/conventional-changelog-angular": { "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", "dev": true, + "license": "ISC", "dependencies": { "compare-func": "^2.0.0", "q": "^1.5.1" @@ -8253,9 +9274,8 @@ }, "node_modules/conventional-changelog-core": { "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", "dev": true, + "license": "MIT", "dependencies": { "add-stream": "^1.0.0", "conventional-changelog-writer": "^5.0.0", @@ -8278,9 +9298,8 @@ }, "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8290,9 +9309,8 @@ }, "node_modules/conventional-changelog-core/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -8302,9 +9320,8 @@ }, "node_modules/conventional-changelog-core/node_modules/normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -8317,9 +9334,8 @@ }, "node_modules/conventional-changelog-core/node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8331,8 +9347,6 @@ }, "node_modules/conventional-changelog-core/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -8347,13 +9361,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/conventional-changelog-core/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -8366,42 +9380,37 @@ }, "node_modules/conventional-changelog-core/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/conventional-changelog-core/node_modules/through2": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-changelog-core/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/conventional-changelog-preset-loader": { "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/conventional-changelog-writer": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", - "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", "dev": true, + "license": "MIT", "dependencies": { "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", @@ -8422,9 +9431,8 @@ }, "node_modules/conventional-changelog-writer/node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8436,8 +9444,6 @@ }, "node_modules/conventional-changelog-writer/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -8452,40 +9458,37 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/conventional-changelog-writer/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/conventional-changelog-writer/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/conventional-changelog-writer/node_modules/through2": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-commits-filter": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, + "license": "MIT", "dependencies": { "lodash.ismatch": "^4.4.0", "modify-values": "^1.0.0" @@ -8496,9 +9499,8 @@ }, "node_modules/conventional-commits-parser": { "version": "3.2.3", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", - "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", "dev": true, + "license": "MIT", "dependencies": { "is-text-path": "^1.0.1", "JSONStream": "^1.0.4", @@ -8516,9 +9518,8 @@ }, "node_modules/conventional-commits-parser/node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8530,8 +9531,6 @@ }, "node_modules/conventional-commits-parser/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -8546,31 +9545,29 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/conventional-commits-parser/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/conventional-commits-parser/node_modules/through2": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "3" } }, "node_modules/conventional-recommended-bump": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", "dev": true, + "license": "MIT", "dependencies": { "concat-stream": "^2.0.0", "conventional-changelog-preset-loader": "^2.3.4", @@ -8590,12 +9587,11 @@ }, "node_modules/conventional-recommended-bump/node_modules/concat-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "engines": [ "node >= 6.0" ], + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -8605,9 +9601,8 @@ }, "node_modules/conventional-recommended-bump/node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8619,8 +9614,6 @@ }, "node_modules/conventional-recommended-bump/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -8635,13 +9628,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/conventional-recommended-bump/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -8654,6 +9647,15 @@ "safe-buffer": "~5.1.1" } }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/copy-descriptor": { "version": "0.1.1", "dev": true, @@ -8776,22 +9778,15 @@ }, "node_modules/core-util-is": { "version": "1.0.2", - "dev": true, "license": "MIT" }, - "node_modules/cosmiconfig": { - "version": "5.1.0", + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "dev": true, - "license": "MIT", - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "lodash.get": "^4.4.2", - "parse-json": "^4.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 0.4.0" } }, "node_modules/cross-env": { @@ -8825,6 +9820,13 @@ "node": ">=4.8" } }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "license": "MIT", + "dependencies": { + "node-fetch": "2.6.7" + } + }, "node_modules/cross-spawn": { "version": "5.1.0", "dev": true, @@ -8843,20 +9845,42 @@ "node": "*" } }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, "node_modules/dargs": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/dashdash": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" }, @@ -8864,11 +9888,24 @@ "node": ">=0.10" } }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/dateformat": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -8883,9 +9920,8 @@ }, "node_modules/debuglog": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -8910,6 +9946,12 @@ "node": ">=0.10.0" } }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, "node_modules/decode-uri-component": { "version": "0.2.0", "dev": true, @@ -8934,16 +9976,11 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, + "node_modules/deep-extend": { + "version": "0.6.0", + "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">=4.0.0" } }, "node_modules/deep-is": { @@ -8951,30 +9988,19 @@ "dev": true, "license": "MIT" }, - "node_modules/default-require-extensions": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-require-extensions/node_modules/strip-bom": { - "version": "4.0.0", + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/defaults": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, + "license": "MIT", "dependencies": { "clone": "^1.0.2" } @@ -9052,40 +10078,27 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/delegates": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "node_modules/depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/deprecation": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "node_modules/detect-file": { - "version": "1.0.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, "node_modules/detect-indent": { "version": "5.0.0", @@ -9095,6 +10108,22 @@ "node": ">=4" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "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/detect-node": { "version": "2.0.5", "dev": true, @@ -9103,27 +10132,26 @@ }, "node_modules/dezalgo": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", "dev": true, + "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, - "node_modules/diff": { - "version": "3.5.0", + "node_modules/diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=0.3.1" + "node": ">= 10.14.2" } }, "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -9133,9 +10161,8 @@ }, "node_modules/dir-glob/node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9151,37 +10178,44 @@ "node": ">=6.0.0" } }, - "node_modules/dot-prop": { - "version": "4.2.0", + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", "dev": true, - "license": "MIT", "dependencies": { - "is-obj": "^1.0.0" + "webidl-conversions": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/duplexer": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/duplexer2": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, + "license": "BSD", "dependencies": { "readable-stream": "~1.1.9" } }, "node_modules/duplexer2/node_modules/readable-stream": { "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -9194,15 +10228,62 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/earcut": { - "version": "2.2.2", + "version": "2.2.4", "license": "ISC" }, + "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/ecc-jsbn": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, + "license": "MIT", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -9226,15 +10307,28 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.3.727", - "dev": true, - "license": "ISC" + "version": "1.4.199", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.199.tgz", + "integrity": "sha512-WIGME0Cs7oob3mxsJwHbeWkH0tYkIE/sjkJ8ML2BYmuRcjhRl/q5kVDXG7W9LOOKwzPU5M0LBlXRq9rlSgnNlg==", + "dev": true }, "node_modules/electron/node_modules/@types/node": { "version": "14.14.35", "dev": true, "license": "MIT" }, + "node_modules/emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, "node_modules/emoji-regex": { "version": "7.0.3", "dev": true, @@ -9251,9 +10345,7 @@ }, "node_modules/encoding": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, + "license": "MIT", "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -9261,9 +10353,7 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "license": "MIT", "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -9274,7 +10364,6 @@ }, "node_modules/end-of-stream": { "version": "1.4.1", - "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -9287,7 +10376,6 @@ }, "node_modules/env-paths": { "version": "2.2.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9295,9 +10383,8 @@ }, "node_modules/envinfo": { "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", "dev": true, + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -9307,9 +10394,7 @@ }, "node_modules/err-code": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true + "license": "MIT" }, "node_modules/error-ex": { "version": "1.3.2", @@ -9321,9 +10406,8 @@ }, "node_modules/es-abstract": { "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -9353,6 +10437,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, "node_modules/es-to-primitive": { "version": "1.2.1", "dev": true, @@ -9372,7 +10462,363 @@ "node_modules/es6-error": { "version": "4.1.1", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true + }, + "node_modules/esbuild": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz", + "integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "esbuild-android-64": "0.14.49", + "esbuild-android-arm64": "0.14.49", + "esbuild-darwin-64": "0.14.49", + "esbuild-darwin-arm64": "0.14.49", + "esbuild-freebsd-64": "0.14.49", + "esbuild-freebsd-arm64": "0.14.49", + "esbuild-linux-32": "0.14.49", + "esbuild-linux-64": "0.14.49", + "esbuild-linux-arm": "0.14.49", + "esbuild-linux-arm64": "0.14.49", + "esbuild-linux-mips64le": "0.14.49", + "esbuild-linux-ppc64le": "0.14.49", + "esbuild-linux-riscv64": "0.14.49", + "esbuild-linux-s390x": "0.14.49", + "esbuild-netbsd-64": "0.14.49", + "esbuild-openbsd-64": "0.14.49", + "esbuild-sunos-64": "0.14.49", + "esbuild-windows-32": "0.14.49", + "esbuild-windows-64": "0.14.49", + "esbuild-windows-arm64": "0.14.49" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz", + "integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz", + "integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz", + "integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz", + "integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz", + "integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz", + "integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz", + "integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz", + "integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz", + "integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz", + "integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz", + "integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz", + "integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz", + "integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz", + "integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz", + "integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz", + "integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz", + "integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz", + "integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz", + "integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz", + "integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, "node_modules/escalade": { "version": "3.1.1", @@ -9390,6 +10836,88 @@ "node": ">=0.8.0" } }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/eslint": { "version": "7.2.0", "dev": true, @@ -9442,12 +10970,94 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-plugin-jsdoc": { + "version": "39.2.9", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.29.0", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.4.0", + "semver": "^7.3.7", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": "^14 || ^16 || ^17 || ^18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.3.7", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, "node_modules/eslint-scope": { - "version": "5.1.0", + "version": "5.1.1", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "esrecurse": "^4.1.0", + "esrecurse": "^4.3.0", "estraverse": "^4.1.1" }, "engines": { @@ -9709,9 +11319,8 @@ }, "node_modules/espree/node_modules/acorn": { "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -9740,7 +11349,7 @@ } }, "node_modules/esquery": { - "version": "1.3.1", + "version": "1.4.0", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9759,16 +11368,24 @@ } }, "node_modules/esrecurse": { - "version": "4.2.1", + "version": "4.3.0", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "4.3.0", "dev": true, @@ -9793,11 +11410,16 @@ "version": "3.1.2", "license": "MIT" }, + "node_modules/exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", + "dev": true + }, "node_modules/execa": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -9818,9 +11440,8 @@ }, "node_modules/execa/node_modules/cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9832,9 +11453,8 @@ }, "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, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9844,9 +11464,8 @@ }, "node_modules/execa/node_modules/is-stream": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -9856,9 +11475,8 @@ }, "node_modules/execa/node_modules/npm-run-path": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -9868,18 +11486,16 @@ }, "node_modules/execa/node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/execa/node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9889,18 +11505,16 @@ }, "node_modules/execa/node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/execa/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -9911,6 +11525,15 @@ "node": ">= 8" } }, + "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/expand-brackets": { "version": "2.1.4", "dev": true, @@ -9950,22 +11573,113 @@ "node": ">=0.10.0" } }, - "node_modules/expand-tilde": { - "version": "2.0.2", + "node_modules/expand-template": { + "version": "2.0.3", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", "dev": true, - "license": "MIT", "dependencies": { - "homedir-polyfill": "^1.0.1" + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" + } + }, + "node_modules/expect/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/expect/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/expect/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/expect/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/expect/node_modules/jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/expect/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/extend-shallow": { "version": "3.0.2", @@ -10143,18 +11857,16 @@ }, "node_modules/extsprintf": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true, "engines": [ "node >=0.6.0" - ] + ], + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { "version": "2.2.6", @@ -10201,6 +11913,15 @@ "reusify": "^1.0.4" } }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "dev": true, @@ -10211,9 +11932,8 @@ }, "node_modules/figures": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -10235,6 +11955,10 @@ "node": ">=4" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "license": "MIT" + }, "node_modules/fill-range": { "version": "4.0.0", "dev": true, @@ -10262,56 +11986,22 @@ }, "node_modules/filter-obj": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.1", "dev": true, "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-cache-dir/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } + "node_modules/find-git-root": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/find-git-root/-/find-git-root-1.0.4.tgz", + "integrity": "sha512-468fmirKKgcrqfZfPn0xIpwZUUsZQcYXfx0RC2/jX39GPz83TwutQNZZhDrI6HqjO8cRejxQVaUY8GQdXopFfA==", + "dev": 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==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -10322,9 +12012,8 @@ }, "node_modules/find-up/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -10334,9 +12023,8 @@ }, "node_modules/find-up/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -10349,9 +12037,8 @@ }, "node_modules/find-up/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -10361,42 +12048,18 @@ }, "node_modules/find-up/node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/find-up/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/findup-sync": { - "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" + "node": ">=8" } }, "node_modules/flat-cache": { @@ -10417,105 +12080,33 @@ "dev": true, "license": "ISC" }, - "node_modules/floss": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "commander": "^7.0.0", - "glob": "^7.1.6", - "mocha": "^8.0.0", - "resolve": "^1.19.0" - }, - "bin": { - "floss": "lib/floss.js" - }, - "engines": { - "node": ">=10.0" - }, - "peerDependencies": { - "electron": ">=12", - "nyc": ">=13" - } - }, - "node_modules/floss/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/floss/node_modules/chalk": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/floss/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/floss/node_modules/commander": { - "version": "7.2.0", + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/floss/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">=8" - } - }, - "node_modules/floss/node_modules/resolve": { - "version": "1.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "node": ">=4.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/floss/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "is-callable": "^1.1.3" } }, "node_modules/for-in": { @@ -10526,86 +12117,18 @@ "node": ">=0.10.0" } }, - "node_modules/foreground-child": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/foreground-child/node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/foreground-child/node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child/node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child/node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child/node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/forever-agent": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/form-data": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -10626,43 +12149,49 @@ "node": ">=0.10.0" } }, - "node_modules/fromentries": { - "version": "1.3.2", - "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/fs-constants": { + "version": "1.0.0", "license": "MIT" }, "node_modules/fs-extra": { - "version": "8.1.0", + "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, - "license": "MIT", "dependencies": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=10" + } + }, + "node_modules/fs-extra/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" } }, "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, + "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, @@ -10672,7 +12201,6 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -10725,15 +12253,6 @@ "dev": true, "license": "ISC" }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.1.1", "dev": true, @@ -10757,9 +12276,8 @@ }, "node_modules/get-pkg-repo": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", "dev": true, + "license": "MIT", "dependencies": { "@hutson/parse-repository-url": "^3.0.0", "hosted-git-info": "^4.0.0", @@ -10775,18 +12293,16 @@ }, "node_modules/get-pkg-repo/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/get-pkg-repo/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -10799,9 +12315,8 @@ }, "node_modules/get-pkg-repo/node_modules/cliui": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -10810,9 +12325,8 @@ }, "node_modules/get-pkg-repo/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -10822,24 +12336,21 @@ }, "node_modules/get-pkg-repo/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 + "dev": true, + "license": "MIT" }, "node_modules/get-pkg-repo/node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-pkg-repo/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -10849,18 +12360,16 @@ }, "node_modules/get-pkg-repo/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/get-pkg-repo/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -10870,9 +12379,8 @@ }, "node_modules/get-pkg-repo/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10884,9 +12392,8 @@ }, "node_modules/get-pkg-repo/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10896,9 +12403,8 @@ }, "node_modules/get-pkg-repo/node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -10913,24 +12419,21 @@ }, "node_modules/get-pkg-repo/node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/get-pkg-repo/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/get-pkg-repo/node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -10946,18 +12449,16 @@ }, "node_modules/get-pkg-repo/node_modules/yargs-parser": { "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/get-port": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -10975,9 +12476,8 @@ }, "node_modules/get-symbol-description": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.1" @@ -10999,9 +12499,8 @@ }, "node_modules/get-workspaces": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/get-workspaces/-/get-workspaces-0.5.2.tgz", - "integrity": "sha512-99x72taQ9OUHhCmBS0B2WI/zwOtBOBPoyVNGs9+B0ag2GGhCjl/EaU9VQ8Zorx64TyVj1Am7bO+0J1KwDqo7OA==", "dev": true, + "license": "MIT", "dependencies": { "@changesets/types": "^0.4.0", "fs-extra": "^7.0.1", @@ -11010,9 +12509,8 @@ }, "node_modules/get-workspaces/node_modules/dir-glob": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^3.0.0" }, @@ -11022,9 +12520,8 @@ }, "node_modules/get-workspaces/node_modules/fs-extra": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -11036,9 +12533,8 @@ }, "node_modules/get-workspaces/node_modules/globby": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", "dev": true, + "license": "MIT", "dependencies": { "@types/glob": "^7.1.1", "array-union": "^1.0.2", @@ -11055,56 +12551,40 @@ }, "node_modules/get-workspaces/node_modules/ignore": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/get-workspaces/node_modules/pify": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/get-workspaces/node_modules/slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/getpass": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/git-branch": { - "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "findup-sync": "^2.0.0" - }, - "engines": { - "node": ">=8" + "assert-plus": "^1.0.0" } }, "node_modules/git-raw-commits": { "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", - "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", "dev": true, + "license": "MIT", "dependencies": { "dargs": "^7.0.0", "lodash": "^4.17.15", @@ -11121,9 +12601,8 @@ }, "node_modules/git-raw-commits/node_modules/readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11135,8 +12614,6 @@ }, "node_modules/git-raw-commits/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -11151,31 +12628,29 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/git-raw-commits/node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/git-raw-commits/node_modules/through2": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, + "license": "MIT", "dependencies": { "readable-stream": "3" } }, "node_modules/git-remote-origin-url": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", "dev": true, + "license": "MIT", "dependencies": { "gitconfiglocal": "^1.0.0", "pify": "^2.3.0" @@ -11186,18 +12661,16 @@ }, "node_modules/git-remote-origin-url/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/git-semver-tags": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, + "license": "MIT", "dependencies": { "meow": "^8.0.0", "semver": "^6.0.0" @@ -11211,18 +12684,16 @@ }, "node_modules/git-semver-tags/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/git-up": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", - "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", "dev": true, + "license": "MIT", "dependencies": { "is-ssh": "^1.3.0", "parse-url": "^6.0.0" @@ -11230,25 +12701,312 @@ }, "node_modules/git-url-parse": { "version": "11.6.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", - "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", "dev": true, + "license": "MIT", "dependencies": { "git-up": "^4.0.0" } }, "node_modules/gitconfiglocal": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, + "license": "BSD", "dependencies": { "ini": "^1.3.2" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "license": "MIT" + }, + "node_modules/gl": { + "version": "5.0.0", + "hasInstallScript": true, + "license": "BSD-2-Clause", + "dependencies": { + "bindings": "^1.5.0", + "bit-twiddle": "^1.0.2", + "glsl-tokenizer": "^2.0.2", + "nan": "^2.15.0", + "node-abi": "^3.5.0", + "node-gyp": "^8.4.1", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/gl/node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/gl/node_modules/are-we-there-yet": { + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/gl/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/gl/node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/gl/node_modules/gauge": { + "version": "4.0.4", + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gl/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/gl/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gl/node_modules/make-fetch-happen": { + "version": "9.1.0", + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/gl/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/gl/node_modules/node-gyp": { + "version": "8.4.1", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/gl/node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/gl/node_modules/npmlog": { + "version": "6.0.2", + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gl/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gl/node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gl/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/gl/node_modules/semver": { + "version": "7.3.7", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gl/node_modules/socks-proxy-agent": { + "version": "6.2.1", + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/gl/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/gl/node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gl/node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gl/node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/gl/node_modules/wide-align": { + "version": "1.1.5", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/gl/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, "node_modules/glob": { "version": "7.1.7", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -11330,34 +13088,6 @@ "license": "ISC", "optional": true }, - "node_modules/global-modules": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/global-tunnel-ng": { "version": "2.7.1", "dev": true, @@ -11398,9 +13128,8 @@ }, "node_modules/globby": { "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -11418,27 +13147,24 @@ }, "node_modules/globby/node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/globby/node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/globby/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, + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -11448,9 +13174,8 @@ }, "node_modules/globby/node_modules/fast-glob": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -11464,9 +13189,8 @@ }, "node_modules/globby/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, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -11476,9 +13200,8 @@ }, "node_modules/globby/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, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -11488,9 +13211,8 @@ }, "node_modules/globby/node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -11500,18 +13222,16 @@ }, "node_modules/globby/node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/globby/node_modules/micromatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -11522,9 +13242,8 @@ }, "node_modules/globby/node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -11532,6 +13251,21 @@ "node": ">=8.0" } }, + "node_modules/glsl-tokenizer": { + "version": "2.1.5", + "license": "MIT", + "dependencies": { + "through2": "^0.6.3" + } + }, + "node_modules/glsl-tokenizer/node_modules/through2": { + "version": "0.6.5", + "license": "MIT", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, "node_modules/got": { "version": "9.6.0", "dev": true, @@ -11566,22 +13300,36 @@ }, "node_modules/graceful-fs": { "version": "4.2.6", - "dev": true, "license": "ISC" }, - "node_modules/growl": { - "version": "1.10.5", + "node_modules/growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.x" + "optional": true + }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" } }, "node_modules/handlebars": { "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -11600,19 +13348,16 @@ }, "node_modules/har-schema": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true, + "license": "ISC", "engines": { "node": ">=4" } }, "node_modules/har-validator": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -11623,9 +13368,8 @@ }, "node_modules/hard-rejection": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11670,9 +13414,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -11685,7 +13428,6 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "dev": true, "license": "ISC" }, "node_modules/has-value": { @@ -11724,57 +13466,23 @@ "node": ">=0.10.0" } }, - "node_modules/hasha": { - "version": "5.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/is-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/highlight.js": { "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": "*" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hosted-git-info": { "version": "2.7.1", "dev": true, @@ -11787,15 +13495,25 @@ }, "node_modules/http-cache-semantics": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } }, "node_modules/http-proxy-agent": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -11807,9 +13525,7 @@ }, "node_modules/http-proxy-agent/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -11824,15 +13540,145 @@ }, "node_modules/http-proxy-agent/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "dev": true, + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-server/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/http-server/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/http-server/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/http-server/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/http-server/node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-server/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-server/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/http-signature": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -11845,9 +13691,7 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -11858,9 +13702,7 @@ }, "node_modules/https-proxy-agent/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -11875,24 +13717,19 @@ }, "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "license": "MIT" }, "node_modules/human-signals": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } }, "node_modules/humanize-ms": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.0.0" } @@ -11908,43 +13745,45 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/ignore-walk": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", - "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", "dev": true, + "license": "ISC", "dependencies": { "minimatch": "^3.0.4" } }, - "node_modules/import-fresh": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true }, "node_modules/import-lazy": { "version": "4.0.0", @@ -11956,9 +13795,8 @@ }, "node_modules/import-local": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -11972,7 +13810,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -11980,22 +13817,17 @@ }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/infer-owner": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true + "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -12003,13 +13835,11 @@ } }, "node_modules/inherits": { - "version": "2.0.3", - "dev": true, + "version": "2.0.4", "license": "ISC" }, "node_modules/ini": { "version": "1.3.5", - "dev": true, "license": "ISC", "engines": { "node": "*" @@ -12017,9 +13847,8 @@ }, "node_modules/init-package-json": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-2.0.5.tgz", - "integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==", "dev": true, + "license": "ISC", "dependencies": { "npm-package-arg": "^8.1.5", "promzard": "^0.3.0", @@ -12035,9 +13864,8 @@ }, "node_modules/init-package-json/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12047,9 +13875,8 @@ }, "node_modules/init-package-json/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -12059,9 +13886,8 @@ }, "node_modules/init-package-json/node_modules/normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -12074,9 +13900,8 @@ }, "node_modules/init-package-json/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -12088,9 +13913,8 @@ }, "node_modules/init-package-json/node_modules/read-package-json": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-4.1.1.tgz", - "integrity": "sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.1", "json-parse-even-better-errors": "^2.3.0", @@ -12103,9 +13927,8 @@ }, "node_modules/init-package-json/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -12118,15 +13941,13 @@ }, "node_modules/init-package-json/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/inquirer": { "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", @@ -12148,18 +13969,16 @@ }, "node_modules/inquirer/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inquirer/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -12172,9 +13991,8 @@ }, "node_modules/inquirer/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -12188,9 +14006,8 @@ }, "node_modules/inquirer/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -12200,33 +14017,29 @@ }, "node_modules/inquirer/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 + "dev": true, + "license": "MIT" }, "node_modules/inquirer/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inquirer/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/inquirer/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -12238,9 +14051,8 @@ }, "node_modules/inquirer/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -12250,9 +14062,8 @@ }, "node_modules/inquirer/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -12262,9 +14073,8 @@ }, "node_modules/internal-slot": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.0", "has": "^1.0.3", @@ -12274,6 +14084,15 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/invert-kv": { "version": "1.0.0", "dev": true, @@ -12284,9 +14103,7 @@ }, "node_modules/ip": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true + "license": "MIT" }, "node_modules/is-accessor-descriptor": { "version": "0.1.6", @@ -12312,17 +14129,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.1", "dev": true, @@ -12344,9 +14150,8 @@ }, "node_modules/is-callable": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -12356,9 +14161,8 @@ }, "node_modules/is-ci": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, + "license": "MIT", "dependencies": { "ci-info": "^2.0.0" }, @@ -12367,9 +14171,9 @@ } }, "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -12397,6 +14201,12 @@ "node": ">= 0.4" } }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, "node_modules/is-descriptor": { "version": "0.1.6", "dev": true, @@ -12418,12 +14228,20 @@ "node": ">=0.10.0" } }, - "node_modules/is-directory": { - "version": "0.3.1", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "license": "MIT", + "optional": true, + "bin": { + "is-docker": "cli.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-extendable": { @@ -12444,7 +14262,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "1.0.0", - "dev": true, "license": "MIT", "dependencies": { "number-is-nan": "^1.0.0" @@ -12453,6 +14270,15 @@ "node": ">=0.10.0" } }, + "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, + "engines": { + "node": ">=6" + } + }, "node_modules/is-glob": { "version": "3.1.0", "dev": true, @@ -12464,11 +14290,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-lambda": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", - "dev": true + "license": "MIT" }, "node_modules/is-module": { "version": "1.0.0", @@ -12508,14 +14353,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-obj": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "dev": true, @@ -12535,6 +14372,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "node_modules/is-reference": { "version": "1.2.1", "dev": true, @@ -12545,9 +14388,8 @@ }, "node_modules/is-regex": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12561,18 +14403,16 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-ssh": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", - "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", "dev": true, + "license": "MIT", "dependencies": { "protocols": "^1.1.0" } @@ -12587,9 +14427,8 @@ }, "node_modules/is-string": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -12616,9 +14455,8 @@ }, "node_modules/is-text-path": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, + "license": "MIT", "dependencies": { "text-extensions": "^1.0.0" }, @@ -12631,11 +14469,22 @@ "dev": true, "license": "MIT" }, + "node_modules/is-unicode-supported": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.2.0.tgz", + "integrity": "sha512-wH+U77omcRzevfIG8dDhTS0V9zZyweakfD01FULl97+0EHiJTTZtJqxPSkIIo/SDPv/i07k/C9jAPY+jwLLeUQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakref": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", - "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.0" }, @@ -12651,18 +14500,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "optional": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "0.0.1", - "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "dev": true, "license": "ISC" }, "node_modules/ismobilejs": { "version": "1.1.1", + "dev": true, "license": "MIT" }, "node_modules/isobject": { @@ -12675,25 +14536,14 @@ }, "node_modules/isstream": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "append-transform": "^2.0.0" - }, "engines": { "node": ">=8" } @@ -12720,27 +14570,120 @@ "semver": "bin/semver.js" } }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.2", + "node_modules/istanbul-lib-report": { + "version": "3.0.0", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", + "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" + "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/cross-spawn": { - "version": "7.0.3", + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.2", "dev": true, "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.0.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", + "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==", + "dev": true, + "dependencies": { + "@jest/core": "^26.6.3", + "import-local": "^3.0.2", + "jest-cli": "^26.6.3" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-changed-files": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz", + "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "execa": "^4.0.0", + "throat": "^5.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-changed-files/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", @@ -12750,65 +14693,91 @@ "node": ">= 8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/jest-changed-files/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, - "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/istanbul-lib-processinfo/node_modules/p-map": { - "version": "3.0.0", + "node_modules/jest-changed-files/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, - "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "pump": "^3.0.0" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-processinfo/node_modules/path-key": { - "version": "3.1.1", + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "license": "ISC", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "path-key": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/semver": { - "version": "6.3.0", + "node_modules/jest-changed-files/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/shebang-command": { + "node_modules/jest-changed-files/node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -12816,18 +14785,20 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/shebang-regex": { + "node_modules/jest-changed-files/node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-processinfo/node_modules/which": { + "node_modules/jest-changed-files/node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -12838,121 +14809,202 @@ "node": ">= 8" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", + "node_modules/jest-cli": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", + "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "@jest/core": "^26.6.3", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "is-ci": "^2.0.0", + "jest-config": "^26.6.3", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "prompts": "^2.0.1", + "yargs": "^15.4.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=8" + "node": ">= 10.14.2" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "6.3.0", + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.2", + "node_modules/jest-config": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.1.2" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.6.3", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">=6.0" + "node": ">= 10.14.2" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "ts-node": { "optional": true } } }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT" + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/istanbul-reports": { + "node_modules/jest-config/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, - "license": "BSD-3-Clause", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "node_modules/jest-config/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": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-worker/node_modules/has-flag": { + "node_modules/jest-config/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/jest-config/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/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==", @@ -12961,7 +15013,29 @@ "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { + "node_modules/jest-config/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/jest-config/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -12973,1524 +15047,1946 @@ "node": ">=8" } }, - "node_modules/jju": { - "version": "1.4.0", + "node_modules/jest-config/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT" + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } }, - "node_modules/js-tokens": { - "version": "4.0.0", + "node_modules/jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", "dev": true, - "license": "MIT" + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } }, - "node_modules/js-yaml": { - "version": "3.13.1", + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "color-convert": "^2.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jscc": { - "version": "1.1.1", + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { - "@jsbits/escape-regex-str": "^1.0.2", - "@jsbits/get-package-version": "^1.0.2", - "magic-string": "^0.25.1", - "perf-regexes": "^1.0.1", - "skip-regex": "^1.0.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jsesc": { - "version": "0.5.0", + "node_modules/jest-diff/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, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/json-buffer": { - "version": "3.0.0", + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=8" + } }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", + "node_modules/jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", "dev": true, - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", + "node_modules/jest-each": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", "dev": true, - "license": "MIT" + "dependencies": { + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT" + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC" + "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/json5": { - "version": "2.2.0", + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/jsonfile": { + "node_modules/jest-each/node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=8" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "engines": [ - "node >= 0.2.0" - ] + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "node_modules/jest-electron": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/jest-electron/-/jest-electron-0.1.12.tgz", + "integrity": "sha512-10Hjr1kpyWz5cj9Xs/Xfb8yvF1LZPVmyEMHu/A/VhgvIV5yiP9uD8FHNc4HAfEnZHM+wvpR5YfveBTUAiNfwnA==", "dev": true, "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "electron": "^11.4.6", + "jest-haste-map": "~24.9.0", + "jest-message-util": "~24.9.0", + "jest-mock": "~24.9.0", + "jest-resolve": "~24.9.0", + "jest-runner": "~24.9.0", + "jest-runtime": "~24.9.0", + "jest-util": "~24.9.0", + "throat": "^5.0.0", + "tslib": "^1.10.0" }, - "bin": { - "JSONStream": "bin.js" + "peerDependencies": { + "jest": "^24.0.0" + } + }, + "node_modules/jest-electron/node_modules/@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "dependencies": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" }, "engines": { - "node": "*" + "node": ">= 6" } }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "node_modules/jest-electron/node_modules/@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/just-extend": { - "version": "4.0.2", + "node_modules/jest-electron/node_modules/@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", "dev": true, - "license": "MIT" + "dependencies": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/keyv": { - "version": "3.1.0", + "node_modules/jest-electron/node_modules/@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", "dev": true, - "license": "MIT", "dependencies": { - "json-buffer": "3.0.0" + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/kind-of": { - "version": "3.2.2", + "node_modules/jest-electron/node_modules/@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", "dev": true, - "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/klaw-sync": { - "version": "6.0.0", + "node_modules/jest-electron/node_modules/@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", "dev": true, - "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.11" + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/lcid": { - "version": "1.0.0", + "node_modules/jest-electron/node_modules/@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", "dev": true, - "license": "MIT", "dependencies": { - "invert-kv": "^1.0.0" + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/lerna": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-4.0.0.tgz", - "integrity": "sha512-DD/i1znurfOmNJb0OBw66NmNqiM8kF6uIrzrJ0wGE3VNdzeOhz9ziWLYiRaZDGGwgbcjOo6eIfcx9O5Qynz+kg==", + "node_modules/jest-electron/node_modules/@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", "dev": true, "dependencies": { - "@lerna/add": "4.0.0", - "@lerna/bootstrap": "4.0.0", - "@lerna/changed": "4.0.0", - "@lerna/clean": "4.0.0", - "@lerna/cli": "4.0.0", - "@lerna/create": "4.0.0", - "@lerna/diff": "4.0.0", - "@lerna/exec": "4.0.0", - "@lerna/import": "4.0.0", - "@lerna/info": "4.0.0", - "@lerna/init": "4.0.0", - "@lerna/link": "4.0.0", - "@lerna/list": "4.0.0", - "@lerna/publish": "4.0.0", - "@lerna/run": "4.0.0", - "@lerna/version": "4.0.0", - "import-local": "^3.0.2", - "npmlog": "^4.1.2" - }, - "bin": { - "lerna": "cli.js" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 6" } }, - "node_modules/levn": { - "version": "0.4.1", + "node_modules/jest-electron/node_modules/@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", "dev": true, - "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-electron/node_modules/@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "node_modules/jest-electron/node_modules/@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-electron/node_modules/acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.4.0" } }, - "node_modules/libnpmaccess": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-4.0.3.tgz", - "integrity": "sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ==", + "node_modules/jest-electron/node_modules/acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "dependencies": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^8.1.2", - "npm-registry-fetch": "^11.0.0" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, + "node_modules/jest-electron/node_modules/acorn-globals/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/libnpmaccess/node_modules/aproba": { + "node_modules/jest-electron/node_modules/acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jest-electron/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/jest-electron/node_modules/anymatch": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } }, - "node_modules/libnpmaccess/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/jest-electron/node_modules/babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" }, "engines": { - "node": ">=6.0" + "node": ">= 6" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/libnpmaccess/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/jest-electron/node_modules/babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/libnpmaccess/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-electron/node_modules/babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/libnpmaccess/node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "node_modules/jest-electron/node_modules/babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", "dev": true, "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" }, "engines": { - "node": ">= 10" + "node": ">= 6" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/libnpmaccess/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/jest-electron/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/jest-electron/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, - "node_modules/libnpmaccess/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/jest-electron/node_modules/cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - }, - "engines": { - "node": ">=10" + "cssom": "0.3.x" } }, - "node_modules/libnpmaccess/node_modules/npm-registry-fetch": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", + "node_modules/jest-electron/node_modules/data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "dev": true, "dependencies": { - "make-fetch-happen": "^9.0.1", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" - }, - "engines": { - "node": ">=10" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" } }, - "node_modules/libnpmaccess/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/jest-electron/node_modules/data-urls/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/jest-electron/node_modules/detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/libnpmaccess/node_modules/socks-proxy-agent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", + "node_modules/jest-electron/node_modules/diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" - }, "engines": { - "node": ">= 10" + "node": ">= 6" } }, - "node_modules/libnpmaccess/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/jest-electron/node_modules/domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "dependencies": { + "webidl-conversions": "^4.0.2" + } }, - "node_modules/libnpmpublish": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-4.0.2.tgz", - "integrity": "sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw==", + "node_modules/jest-electron/node_modules/electron": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-11.5.0.tgz", + "integrity": "sha512-WjNDd6lGpxyiNjE3LhnFCAk/D9GIj1rU3GSDealVShhkkkPR3Vh4q8ErXGDl1OAO/faomVa10KoFPUN/pLbNxg==", "dev": true, + "hasInstallScript": true, "dependencies": { - "normalize-package-data": "^3.0.2", - "npm-package-arg": "^8.1.2", - "npm-registry-fetch": "^11.0.0", - "semver": "^7.1.3", - "ssri": "^8.0.1" + "@electron/get": "^1.0.1", + "@types/node": "^12.0.12", + "extract-zip": "^1.0.3" + }, + "bin": { + "electron": "cli.js" }, "engines": { - "node": ">=10" + "node": ">= 8.6" } }, - "node_modules/libnpmpublish/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/jest-electron/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-electron/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">=6.0" + "node": ">=4.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/libnpmpublish/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/jest-electron/node_modules/expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/libnpmpublish/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-electron/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "locate-path": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/libnpmpublish/node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "node_modules/jest-electron/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "bindings": "^1.5.0", + "nan": "^2.12.1" }, "engines": { - "node": ">= 10" + "node": ">= 4.0" } }, - "node_modules/libnpmpublish/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/jest-electron/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "node_modules/libnpmpublish/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "node_modules/jest-electron/node_modules/html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, + "whatwg-encoding": "^1.0.1" + } + }, + "node_modules/jest-electron/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": ">=10" + "node": ">=4" } }, - "node_modules/libnpmpublish/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/jest-electron/node_modules/istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/libnpmpublish/node_modules/npm-registry-fetch": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", + "node_modules/jest-electron/node_modules/istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", "dev": true, "dependencies": { - "make-fetch-happen": "^9.0.1", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/libnpmpublish/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/jest-electron/node_modules/jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/libnpmpublish/node_modules/socks-proxy-agent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", + "node_modules/jest-electron/node_modules/jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", "dev": true, "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" }, "engines": { - "node": ">= 10" + "node": ">= 6" } }, - "node_modules/libnpmpublish/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/lines-and-columns": { - "version": "1.1.6", + "node_modules/jest-electron/node_modules/jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", "dev": true, - "license": "MIT" + "dependencies": { + "detect-newline": "^2.1.0" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/linkify-it": { - "version": "3.0.2", + "node_modules/jest-electron/node_modules/jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", "dev": true, - "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/load-json-file": { - "version": "4.0.0", + "node_modules/jest-electron/node_modules/jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", "dev": true, - "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/locate-path": { - "version": "2.0.0", + "node_modules/jest-electron/node_modules/jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/lodash": { - "version": "4.17.21", + "node_modules/jest-electron/node_modules/jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", "dev": true, - "license": "MIT" - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.flow": { - "version": "3.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" + "engines": { + "node": ">= 6" + } }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "node_modules/jest-electron/node_modules/jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", "dev": true, "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "engines": { + "node": ">= 6" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" } }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "node_modules/jest-electron/node_modules/jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", "dev": true, "dependencies": { - "lodash._reinterpolate": "^3.0.0" + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/log-symbols": { - "version": "4.0.0", + "node_modules/jest-electron/node_modules/jest-jasmine2/node_modules/throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==", + "dev": true + }, + "node_modules/jest-electron/node_modules/jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", "dev": true, - "license": "MIT", "dependencies": { - "chalk": "^4.0.0" + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/jest-electron/node_modules/jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", "dev": true, - "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 6" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.0", + "node_modules/jest-electron/node_modules/jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 6" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/jest-electron/node_modules/jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">= 6" } }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/jest-electron/node_modules/jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", "dev": true, - "license": "MIT", + "dependencies": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/jest-electron/node_modules/jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/lolex": { + "node_modules/jest-electron/node_modules/jest-runner/node_modules/throat": { "version": "4.1.0", - "dev": true, - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==", + "dev": true }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "node_modules/jest-electron/node_modules/jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + }, + "bin": { + "jest-runtime": "bin/jest-runtime.js" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/lowercase-keys": { - "version": "1.0.1", + "node_modules/jest-electron/node_modules/jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/lru-cache": { - "version": "4.1.1", + "node_modules/jest-electron/node_modules/jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", "dev": true, - "license": "ISC", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/magic-string": { - "version": "0.25.2", + "node_modules/jest-electron/node_modules/jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, - "license": "MIT", "dependencies": { - "sourcemap-codec": "^1.4.4" + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/make-dir": { - "version": "1.3.0", + "node_modules/jest-electron/node_modules/jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", "dev": true, - "license": "MIT", "dependencies": { - "pify": "^3.0.0" + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/make-error": { - "version": "1.3.6", - "dev": true, - "license": "ISC" - }, - "node_modules/make-fetch-happen": { - "version": "8.0.14", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", - "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "node_modules/jest-electron/node_modules/jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.0.5", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^5.0.0", - "ssri": "^8.0.0" + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" }, "engines": { - "node": ">= 10" + "node": ">= 6" } }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-electron/node_modules/jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "dependencies": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "node_modules/jest-electron/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/map-cache": { - "version": "0.2.2", + "node_modules/jest-electron/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, - "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/map-obj": { - "version": "1.0.1", + "node_modules/jest-electron/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, - "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/map-visit": { - "version": "1.0.0", + "node_modules/jest-electron/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, - "license": "MIT", "dependencies": { - "object-visit": "^1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/markdown-it": { - "version": "11.0.1", + "node_modules/jest-electron/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "p-try": "^2.0.0" }, - "bin": { - "markdown-it": "bin/markdown-it.js" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/markdown-it-highlightjs": { - "version": "3.4.0", + "node_modules/jest-electron/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, - "license": "Unlicense", "dependencies": { - "highlight.js": "^10.2.0", - "lodash.flow": "^3.5.0" - } - }, - "node_modules/marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", - "dev": true, - "bin": { - "marked": "bin/marked" + "p-limit": "^2.0.0" }, "engines": { - "node": ">= 8.16.2" + "node": ">=6" } }, - "node_modules/matcher": { - "version": "3.0.0", + "node_modules/jest-electron/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/matcher/node_modules/escape-string-regexp": { + "node_modules/jest-electron/node_modules/parse5": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "node_modules/jest-electron/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true, - "license": "MIT", - "optional": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/mdurl": { - "version": "1.0.1", + "node_modules/jest-electron/node_modules/pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", "dev": true, - "license": "MIT" + "dependencies": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/mem": { - "version": "1.1.0", + "node_modules/jest-electron/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/jest-electron/node_modules/read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, - "license": "MIT", "dependencies": { - "mimic-fn": "^1.0.0" + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/memorystream": { - "version": "0.3.1", + "node_modules/jest-electron/node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/jest-electron/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "engines": { - "node": ">= 0.10.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "node_modules/jest-electron/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/jest-electron/node_modules/stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/meow/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-electron/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": { - "yallist": "^4.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/meow/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "node_modules/jest-electron/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": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "ansi-regex": "^4.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/meow/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==", + "node_modules/jest-electron/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "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" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/jest-electron/node_modules/test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "node_modules/jest-electron/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", "dev": true, "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "punycode": "^2.1.0" } }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/jest-electron/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "node_modules/jest-electron/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/jest-electron/node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "iconv-lite": "0.4.24" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/jest-electron/node_modules/whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "node_modules/jest-electron/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": ">=8" + "node": ">=6" } }, - "node_modules/meow/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/jest-electron/node_modules/write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/jest-electron/node_modules/ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "async-limiter": "~1.0.0" } }, - "node_modules/meow/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/jest-electron/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/jest-electron/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/jest-electron/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, - "engines": { - "node": ">= 8" + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/micromatch": { - "version": "3.1.10", + "node_modules/jest-environment-jsdom": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", "dev": true, - "license": "MIT", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" } }, - "node_modules/micromatch/node_modules/kind-of": { - "version": "6.0.2", + "node_modules/jest-environment-jsdom/node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, - "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "@types/node": "*" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" } }, - "node_modules/mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "node_modules/jest-environment-node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", "dev": true, + "dependencies": { + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + }, "engines": { - "node": ">= 0.6" + "node": ">= 10.14.2" } }, - "node_modules/mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "dependencies": { - "mime-db": "1.50.0" + "@jest/types": "^26.6.2", + "@types/node": "*" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.14.2" } }, - "node_modules/mimic-fn": { - "version": "1.2.0", + "node_modules/jest-extended": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-1.2.1.tgz", + "integrity": "sha512-eKZR5iDpyTkcDesj16FpIPnjAWQNUB81ZFQW08EIddM6iqO7DjRIi39td9qol+1dpJS4Mqr9Qzp8ZMhanbSeug==", "dev": true, - "license": "MIT", + "dependencies": { + "expect": "^26.6.2", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.4" + }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/mimic-response": { - "version": "1.0.1", + "node_modules/jest-extended/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/jest-extended/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": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/minimatch": { - "version": "3.0.4", + "node_modules/jest-extended/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/minimist": { - "version": "1.2.5", - "dev": true, - "license": "MIT" - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/jest-extended/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": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/minimist-options/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/jest-extended/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/minipass": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", + "node_modules/jest-extended/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, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "node_modules/jest-extended/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">= 8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "node_modules/jest-extended/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-extended/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">=8" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-extended/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" }, - "optionalDependencies": { - "encoding": "^0.1.12" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/jest-extended/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "node_modules/jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", "dev": true, "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "engines": { + "node": ">= 10.14.2" + }, + "optionalDependencies": { + "fsevents": "^2.1.2" } }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/jest-haste-map/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": { - "minipass": "^3.0.0" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/jest-haste-map/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": { - "minipass": "^3.0.0" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/jest-haste-map/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/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/jest-haste-map/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 8" + "node": ">=8.6" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/missionlog": { - "version": "1.6.0", + "node_modules/jest-haste-map/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.4", - "core-js": "^3.6.4" + "is-number": "^7.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8.0" } }, - "node_modules/mixin-deep": { - "version": "1.3.1", + "node_modules/jest-jasmine2": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", "dev": true, - "license": "MIT", "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" } }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/jest-jasmine2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "node_modules/jest-jasmine2/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": { - "minimist": "^1.2.5" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/mkdirp-infer-owner": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", - "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", + "node_modules/jest-jasmine2/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": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/mkdirp-infer-owner/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/jest-jasmine2/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, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/mocha": { - "version": "8.3.2", + "node_modules/jest-jasmine2/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "has-flag": "^4.0.0" }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", + "dev": true, + "dependencies": { + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">= 10.12.0" + "node": ">= 10.14.2" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.0", + "node_modules/jest-matcher-utils/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/ansi-styles": { + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -14501,25 +16997,27 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/mocha/node_modules/color-convert": { + "node_modules/jest-matcher-utils/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -14527,785 +17025,808 @@ "node": ">=7.0.0" } }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", + "node_modules/jest-matcher-utils/node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=0.3.1" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/escape-string-regexp": { + "node_modules/jest-matcher-utils/node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", + "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, - "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", + "node_modules/jest-matcher-utils/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "dev": true, - "license": "ISC", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.6", + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, - "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.0.0", + "node_modules/jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", "dev": true, - "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.1.20", + "node_modules/jest-message-util/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, - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "fill-range": "^7.0.1" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=8" } }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/mocha/node_modules/path-exists": { + "node_modules/jest-message-util/node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "5.0.1", + "node_modules/jest-message-util/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=0.12.0" } }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.2", + "node_modules/jest-message-util/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "6.0.0", + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", + "node_modules/jest-message-util/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8.0" } }, - "node_modules/mocha/node_modules/which": { - "version": "2.0.2", + "node_modules/jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, - "license": "ISC", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "@jest/types": "^24.9.0" }, "engines": { - "node": ">= 8" + "node": ">= 6" } }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 6" } }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.5", + "node_modules/jest-mock/node_modules/@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "dependencies": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", + "node_modules/jest-mock/node_modules/@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", "dev": true, - "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" + "@types/yargs-parser": "*" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true, - "license": "ISC", "engines": { - "node": ">=10" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/modify-values": { + "node_modules/jest-raw-loader": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "resolved": "https://registry.npmjs.org/jest-raw-loader/-/jest-raw-loader-1.0.1.tgz", + "integrity": "sha512-g9oaAjeC4/rIJk1Wd3RxVbOfMizowM7LSjEJqa4R9qDX0OjQNABXOhH+GaznUp+DjTGVPi2vPPbQXyX87DOnYg==", + "dev": true + }, + "node_modules/jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 10.14.2" } }, - "node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/multimatch": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", - "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "node_modules/jest-resolve": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", "dev": true, "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.14.2" } }, - "node_modules/multimatch/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/jest-resolve-dependencies": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz", + "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==", "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-snapshot": "^26.6.2" + }, "engines": { - "node": ">=8" + "node": ">= 10.14.2" } }, - "node_modules/multimatch/node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "node_modules/jest-resolve/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/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.1.18", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/nanomatch": { - "version": "1.2.13", + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.2", + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "node_modules/jest-resolve/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": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", + "node_modules/jest-resolve/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, - "license": "MIT" + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/nise": { - "version": "1.5.0", + "node_modules/jest-resolve/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/formatio": "^3.1.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^4.1.0", - "path-to-regexp": "^1.7.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-fetch": { - "version": "2.6.1", + "node_modules/jest-resolve/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, - "license": "MIT", "engines": { - "node": "4.x || >=6.0.0" + "node": ">=8" } }, - "node_modules/node-gyp": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz", - "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==", + "node_modules/jest-resolve/node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { - "node-gyp": "bin/node-gyp.js" + "resolve": "bin/resolve" }, - "engines": { - "node": ">= 6.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-gyp/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/node-gyp/node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "minipass": "^2.6.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/node-gyp/node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "node_modules/jest-runner": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", "dev": true, "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/node-gyp/node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.7.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-runner/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": { - "minipass": "^2.9.0" - } - }, - "node_modules/node-gyp/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/node-gyp/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/node-gyp/node_modules/tar": { - "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "node_modules/jest-runner/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": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4.5" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/node-gyp/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/jest-runner/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": { - "isexe": "^2.0.0" + "color-name": "~1.1.4" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/node-gyp/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/node-preload": { - "version": "0.2.1", + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", - "dependencies": { - "process-on-spawn": "^1.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/node-releases": { - "version": "1.1.71", - "dev": true, - "license": "MIT" - }, - "node_modules/noms": { - "version": "0.0.0", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "ISC", "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "~1.0.31" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "node_modules/jest-runtime": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", "dev": true, "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^0.6.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.4.1" }, "bin": { - "nopt": "bin/nopt.js" + "jest-runtime": "bin/jest-runtime.js" + }, + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "node_modules/jest-runtime/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/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "node_modules/jest-runtime/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": { - "npm-normalize-package-bin": "^1.0.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/npm-conf": { - "version": "1.1.3", + "node_modules/jest-runtime/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/jest-runtime/node_modules/jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, - "license": "MIT", - "optional": true, "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" + "@jest/types": "^26.6.2", + "@types/node": "*" }, "engines": { - "node": ">=4" + "node": ">= 10.14.2" } }, - "node_modules/npm-install-checks": { + "node_modules/jest-runtime/node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", - "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, - "dependencies": { - "semver": "^7.1.1" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npm-install-checks/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npm-install-checks/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@types/node": "*", + "graceful-fs": "^4.2.4" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/npm-install-checks/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/npm-lifecycle": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz", - "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", + "node_modules/jest-snapshot": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", "dev": true, "dependencies": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" + "@babel/types": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.14.2" } }, - "node_modules/npm-lifecycle/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/jest-snapshot/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": { - "isexe": "^2.0.0" + "color-convert": "^2.0.1" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "node_modules/npm-package-arg": { - "version": "6.1.0", + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "ISC", "dependencies": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/npm-packlist": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz", - "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==", + "node_modules/jest-snapshot/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": { - "glob": "^7.1.6", - "ignore-walk": "^3.0.3", - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "bin": { - "npm-packlist": "bin/index.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/npm-pick-manifest": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", - "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "node_modules/jest-snapshot/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, - "dependencies": { - "npm-install-checks": "^4.0.0", - "npm-normalize-package-bin": "^1.0.1", - "npm-package-arg": "^8.1.2", - "semver": "^7.3.4" + "engines": { + "node": ">=8" } }, - "node_modules/npm-pick-manifest/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/npm-pick-manifest/node_modules/lru-cache": { + "node_modules/jest-snapshot/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", @@ -15317,719 +17838,777 @@ "node": ">=10" } }, - "node_modules/npm-pick-manifest/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/npm-pick-manifest/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npm-pick-manifest/node_modules/yallist": { + "node_modules/jest-snapshot/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/npm-registry-fetch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz", - "integrity": "sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==", + "node_modules/jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", "dev": true, "dependencies": { - "@npmcli/ci-detect": "^1.0.0", - "lru-cache": "^6.0.0", - "make-fetch-happen": "^8.0.9", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" }, "engines": { - "node": ">=10" + "node": ">= 10.14.2" } }, - "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "node_modules/jest-util/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": { - "lru-cache": "^6.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm-registry-fetch/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/jest-util/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": { - "yallist": "^4.0.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "node_modules/jest-util/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": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - } - }, - "node_modules/npm-registry-fetch/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/npm-registry-fetch/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/npm-run-all": { - "version": "4.1.5", + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 4" + "node": ">=7.0.0" } }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.5", + "node_modules/jest-util/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, - "license": "MIT", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=4.8" + "node": ">=8" } }, - "node_modules/npm-run-path": { - "version": "2.0.2", + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, "engines": { - "node": ">=4" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "node": ">=8" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", + "node_modules/jest-util/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.12.0" } }, - "node_modules/nyc": { - "version": "15.1.0", + "node_modules/jest-util/node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, - "license": "ISC", "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8.9" + "node": ">=8.6" } }, - "node_modules/nyc/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nyc/node_modules/p-map": { - "version": "3.0.0", + "node_modules/jest-util/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=8.0" } }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", "dev": true, - "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" + }, "engines": { - "node": ">=8" + "node": ">= 10.14.2" } }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "color-convert": "^2.0.1" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/nyc/node_modules/semver": { + "node_modules/jest-validate/node_modules/camelcase": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-copy": { - "version": "0.1.0", + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "is-descriptor": "^0.1.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.11.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.0" } }, - "node_modules/object-keys": { - "version": "1.1.1", + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/object-visit": { - "version": "1.0.1", + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "isobject": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/object.assign": { - "version": "4.1.2", + "node_modules/jest-watcher": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", + "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^26.6.2", + "string-length": "^4.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 10.14.2" } }, - "node_modules/object.fromentries": { - "version": "2.0.3", + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "node_modules/jest-watcher/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": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/object.pick": { - "version": "1.3.0", + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/once": { - "version": "1.4.0", + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=8" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/onetime/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/open-sans-fonts": { - "version": "1.6.2", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/optionator": { - "version": "0.9.1", + "node_modules/jest-worker": { + "version": "26.6.2", "dev": true, "license": "MIT", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/os-locale": { - "version": "2.1.0", + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/os-locale/node_modules/execa": { - "version": "0.7.0", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/os-shim": { - "version": "0.1.3", + "node_modules/jju": { + "version": "1.4.0", "dev": true, - "engines": { - "node": ">= 0.4.0" - } + "license": "MIT" }, - "node_modules/os-tmpdir": { - "version": "1.0.2", + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/osenv": { - "version": "0.1.5", + "node_modules/js-tokens": { + "version": "4.0.0", "dev": true, - "license": "ISC", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } + "license": "MIT" }, - "node_modules/p-cancelable": { - "version": "1.1.0", + "node_modules/js-yaml": { + "version": "3.13.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/p-finally": { - "version": "1.0.0", + "node_modules/jsbn": { + "version": "0.1.1", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/p-limit": { - "version": "1.3.0", + "node_modules/jscc": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^1.0.0" + "@jsbits/escape-regex-str": "^1.0.2", + "@jsbits/get-package-version": "^1.0.2", + "magic-string": "^0.25.1", + "perf-regexes": "^1.0.1", + "skip-regex": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">=6.0" } }, - "node_modules/p-locate": { - "version": "2.0.0", + "node_modules/jsdoc-type-pratt-parser": { + "version": "3.0.1", "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">=12.0.0" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.0" + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" }, "engines": { "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/p-map-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", - "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", + "node_modules/jsdom/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true, + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/p-pipe": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz", - "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==", + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 6" } }, - "node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "node_modules/jsdom/node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", "dev": true, "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" + "whatwg-encoding": "^1.0.5" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/p-queue/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/p-reduce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "node_modules/jsdom/node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" + "iconv-lite": "0.4.24" } }, - "node_modules/p-try": { - "version": "1.0.0", + "node_modules/json-buffer": { + "version": "3.0.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/p-waterfall": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz", - "integrity": "sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==", + "node_modules/json-parse-better-errors": { + "version": "1.0.2", "dev": true, - "dependencies": { - "p-reduce": "^2.0.0" + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/package-hash": { + "node_modules/jsonc-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", + "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "dev": true + }, + "node_modules/jsonfile": { "version": "4.0.0", "dev": true, - "license": "ISC", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/pacote": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz", - "integrity": "sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg==", + "node_modules/jsprim": { + "version": "1.4.1", "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", "dependencies": { - "@npmcli/git": "^2.1.0", - "@npmcli/installed-package-contents": "^1.0.6", - "@npmcli/promise-spawn": "^1.2.0", - "@npmcli/run-script": "^1.8.2", - "cacache": "^15.0.5", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.3", - "mkdirp": "^1.0.3", - "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.4", - "npm-pick-manifest": "^6.0.0", - "npm-registry-fetch": "^11.0.0", - "promise-retry": "^2.0.1", - "read-package-json-fast": "^2.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.1.0" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/keyv": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "deprecated": "use String.prototype.padStart()", + "dev": true + }, + "node_modules/lerna": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/add": "4.0.0", + "@lerna/bootstrap": "4.0.0", + "@lerna/changed": "4.0.0", + "@lerna/clean": "4.0.0", + "@lerna/cli": "4.0.0", + "@lerna/create": "4.0.0", + "@lerna/diff": "4.0.0", + "@lerna/exec": "4.0.0", + "@lerna/import": "4.0.0", + "@lerna/info": "4.0.0", + "@lerna/init": "4.0.0", + "@lerna/link": "4.0.0", + "@lerna/list": "4.0.0", + "@lerna/publish": "4.0.0", + "@lerna/run": "4.0.0", + "@lerna/version": "4.0.0", + "import-local": "^3.0.2", + "npmlog": "^4.1.2" }, "bin": { - "pacote": "lib/bin.js" + "lerna": "cli.js" + }, + "engines": { + "node": ">= 10.18.0" + } + }, + "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/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libnpmaccess": { + "version": "4.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "minipass": "^3.1.1", + "npm-package-arg": "^8.1.2", + "npm-registry-fetch": "^11.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/pacote/node_modules/debug": { + "node_modules/libnpmaccess/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/libnpmaccess/node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -16042,11 +18621,10 @@ } } }, - "node_modules/pacote/node_modules/hosted-git-info": { + "node_modules/libnpmaccess/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -16054,11 +18632,10 @@ "node": ">=10" } }, - "node_modules/pacote/node_modules/lru-cache": { + "node_modules/libnpmaccess/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -16066,11 +18643,10 @@ "node": ">=10" } }, - "node_modules/pacote/node_modules/make-fetch-happen": { + "node_modules/libnpmaccess/node_modules/make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dev": true, + "license": "ISC", "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -16093,29 +18669,15 @@ "node": ">= 10" } }, - "node_modules/pacote/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pacote/node_modules/ms": { + "node_modules/libnpmaccess/node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, - "node_modules/pacote/node_modules/npm-package-arg": { + "node_modules/libnpmaccess/node_modules/npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, + "license": "ISC", "dependencies": { "hosted-git-info": "^4.0.1", "semver": "^7.3.4", @@ -16125,11 +18687,10 @@ "node": ">=10" } }, - "node_modules/pacote/node_modules/npm-registry-fetch": { + "node_modules/libnpmaccess/node_modules/npm-registry-fetch": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", "dev": true, + "license": "ISC", "dependencies": { "make-fetch-happen": "^9.0.1", "minipass": "^3.1.3", @@ -16142,26 +18703,10 @@ "node": ">=10" } }, - "node_modules/pacote/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/pacote/node_modules/semver": { + "node_modules/libnpmaccess/node_modules/semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -16172,11 +18717,10 @@ "node": ">=10" } }, - "node_modules/pacote/node_modules/socks-proxy-agent": { + "node_modules/libnpmaccess/node_modules/socks-proxy-agent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.1", @@ -16186,562 +18730,557 @@ "node": ">= 10" } }, - "node_modules/pacote/node_modules/yallist": { + "node_modules/libnpmaccess/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, - "node_modules/parent-module": { - "version": "1.0.1", + "node_modules/libnpmpublish": { + "version": "4.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "callsites": "^3.0.0" + "normalize-package-data": "^3.0.2", + "npm-package-arg": "^8.1.2", + "npm-registry-fetch": "^11.0.0", + "semver": "^7.1.3", + "ssri": "^8.0.1" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/parent-module/node_modules/callsites": { - "version": "3.1.0", + "node_modules/libnpmpublish/node_modules/debug": { + "version": "4.3.2", "dev": true, "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=6" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/parse-github-url": { - "version": "1.0.2", + "node_modules/libnpmpublish/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, - "license": "MIT", - "bin": { - "parse-github-url": "cli.js" + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/parse-json": { - "version": "4.0.0", + "node_modules/libnpmpublish/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", + "node_modules/libnpmpublish/node_modules/make-fetch-happen": { + "version": "9.1.0", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/parse-path": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", - "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", + "node_modules/libnpmpublish/node_modules/ms": { + "version": "2.1.2", "dev": true, - "dependencies": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0", - "qs": "^6.9.4", - "query-string": "^6.13.8" - } + "license": "MIT" }, - "node_modules/parse-url": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", - "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", + "node_modules/libnpmpublish/node_modules/normalize-package-data": { + "version": "3.0.3", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "is-ssh": "^1.3.0", - "normalize-url": "^6.1.0", - "parse-path": "^4.0.0", - "protocols": "^1.4.0" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/pascalcase": { - "version": "0.1.1", + "node_modules/libnpmpublish/node_modules/npm-package-arg": { + "version": "8.1.5", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/path-dirname": { - "version": "1.0.2", + "node_modules/libnpmpublish/node_modules/npm-registry-fetch": { + "version": "11.0.0", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "make-fetch-happen": "^9.0.1", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/path-exists": { - "version": "3.0.0", + "node_modules/libnpmpublish/node_modules/semver": { + "version": "7.3.5", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", + "node_modules/libnpmpublish/node_modules/socks-proxy-agent": { + "version": "6.1.0", "dev": true, "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/path-key": { - "version": "2.0.1", + "node_modules/libnpmpublish/node_modules/yallist": { + "version": "4.0.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "license": "ISC" + }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" } }, - "node_modules/path-parse": { - "version": "1.0.6", + "node_modules/lines-and-columns": { + "version": "1.1.6", "dev": true, "license": "MIT" }, - "node_modules/path-to-regexp": { - "version": "1.7.0", + "node_modules/linkify-it": { + "version": "3.0.2", "dev": true, "license": "MIT", "dependencies": { - "isarray": "0.0.1" + "uc.micro": "^1.0.1" } }, - "node_modules/path-type": { - "version": "3.0.0", + "node_modules/load-json-file": { + "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { - "pify": "^3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "node_modules/localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", "dev": true, + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/pend": { - "version": "1.2.0", + "node_modules/lodash": { + "version": "4.17.21", "dev": true, "license": "MIT" }, - "node_modules/perf_hooks": { - "version": "0.0.1", + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", "dev": true, "license": "MIT" }, - "node_modules/perf-regexes": { - "version": "1.0.1", + "node_modules/lodash.flow": { + "version": "3.5.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.14" - } + "license": "MIT" }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "node_modules/lodash.get": { + "version": "4.4.2", + "dev": true, + "license": "MIT" }, - "node_modules/physical-cpu-count": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz", - "integrity": "sha1-GN4vl+S/epVRrXURlCtUlverpmA=", - "dev": true + "node_modules/lodash.isequal": { + "version": "4.5.0", + "dev": true, + "license": "MIT" }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "node_modules/lodash.ismatch": { + "version": "4.4.0", "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } + "license": "MIT" }, - "node_modules/pify": { - "version": "3.0.0", + "node_modules/lodash.merge": { + "version": "4.6.2", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pixi.js": { - "resolved": "bundles/pixi.js", - "link": true - }, - "node_modules/pixi.js-legacy": { - "resolved": "bundles/pixi.js-legacy", - "link": true + "license": "MIT" }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true }, - "node_modules/pkg-up": { - "version": "3.1.0", + "node_modules/lodash.template": { + "version": "4.5.0", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", + "node_modules/lodash.templatesettings": { + "version": "4.2.0", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" + "lodash._reinterpolate": "^3.0.0" } }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", + "node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, - "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/log-symbols/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, - "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", + "node_modules/lowercase-keys": { + "version": "1.0.1", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/pre-commit": { - "version": "1.2.2", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^5.0.1", - "spawn-sync": "^1.0.15", - "which": "1.2.x" - } + "node_modules/lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true }, - "node_modules/pre-commit/node_modules/which": { - "version": "1.2.14", + "node_modules/lru-cache": { + "version": "4.1.1", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/prepend-http": { - "version": "2.0.0", + "node_modules/magic-string": { + "version": "0.25.2", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "sourcemap-codec": "^1.4.4" } }, - "node_modules/process-nextick-args": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "dev": true, + "node_modules/make-dir": { + "version": "3.1.0", "license": "MIT", "dependencies": { - "fromentries": "^1.2.0" + "semver": "^6.0.0" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/progress": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "node_modules/promise-polyfill": { - "version": "8.2.0", - "license": "MIT" + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/make-fetch-happen": { + "version": "8.0.14", "dev": true, + "license": "ISC", "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" }, "engines": { - "node": ">=10" + "node": ">= 10" } }, - "node_modules/promzard": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "read": "1" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "dev": true, - "license": "ISC" - }, - "node_modules/protocols": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", - "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", - "dev": true - }, - "node_modules/pseudomap": { - "version": "1.0.2", + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", "dev": true, "license": "ISC" }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "tmpl": "1.0.5" } }, - "node_modules/punycode": { - "version": "2.1.1", + "node_modules/map-cache": { + "version": "0.2.2", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "node_modules/map-obj": { + "version": "1.0.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": ">=0.10.0" } }, - "node_modules/qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "node_modules/map-visit": { + "version": "1.0.0", "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.0.4" + "object-visit": "^1.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "node_modules/markdown-it": { + "version": "11.0.1", "dev": true, + "license": "MIT", "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "node_modules/querystring": { - "version": "0.2.0", - "engines": { - "node": ">=0.4.x" + "node_modules/markdown-it-highlightjs": { + "version": "3.4.0", + "dev": true, + "license": "Unlicense", + "dependencies": { + "highlight.js": "^10.2.0", + "lodash.flow": "^3.5.0" } }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "node_modules/matcher": { + "version": "3.0.0", "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/randombytes": { - "version": "2.1.0", + "node_modules/matcher/node_modules/escape-string-regexp": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "node_modules/mdurl": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/mem": { + "version": "1.1.0", "dev": true, + "license": "MIT", "dependencies": { - "mute-stream": "~0.0.4" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">=0.8" + "node": ">=4" } }, - "node_modules/read-cmd-shim": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz", - "integrity": "sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==", - "dev": true - }, - "node_modules/read-package-json": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-3.0.1.tgz", - "integrity": "sha512-aLcPqxovhJTVJcsnROuuzQvv6oziQx4zd3JvG0vGCL5MjTONUc4uJ90zCBC6R7W7oUKBNoR/F8pkyfVwlbxqng==", + "node_modules/memorystream": { + "version": "0.3.1", "dev": true, - "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" - }, "engines": { - "node": ">=10" + "node": ">= 0.10.0" } }, - "node_modules/read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "node_modules/meow": { + "version": "8.1.2", "dev": true, + "license": "MIT", "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-package-json/node_modules/hosted-git-info": { + "node_modules/meow/node_modules/hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -16749,11 +19288,10 @@ "node": ">=10" } }, - "node_modules/read-package-json/node_modules/lru-cache": { + "node_modules/meow/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -16761,11 +19299,10 @@ "node": ">=10" } }, - "node_modules/read-package-json/node_modules/normalize-package-data": { + "node_modules/meow/node_modules/normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -16776,1333 +19313,1276 @@ "node": ">=10" } }, - "node_modules/read-package-json/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/meow/node_modules/parse-json": { + "version": "5.2.0", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@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": ">=10" - } - }, - "node_modules/read-package-json/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/read-package-tree": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", - "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", - "dev": true, - "dependencies": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "node_modules/read-package-tree/node_modules/read-package-json": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", - "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", - "dev": true, - "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", "dev": true, + "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/readable-stream": { - "version": "1.0.34", + "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "node_modules/meow/node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", "dev": true, - "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/readdirp": { - "version": "3.5.0", + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=8.10.0" + "node": ">=8" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "node_modules/meow/node_modules/semver": { + "version": "7.3.5", "dev": true, + "license": "ISC", "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/regenerate": { - "version": "1.4.0", + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", "dev": true, - "license": "MIT" - }, - "node_modules/regenerator-runtime": { - "version": "0.13.7", - "dev": true, - "license": "MIT" - }, - "node_modules/regex-not": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.1.0", - "dev": true, - "license": "MIT", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regjsgen": { - "version": "0.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/regjsparser": { - "version": "0.6.0", + "node_modules/meow/node_modules/yallist": { + "version": "4.0.0", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } + "license": "ISC" }, - "node_modules/release-zalgo": { - "version": "1.0.0", + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", "dev": true, "license": "ISC", - "dependencies": { - "es6-error": "^4.0.1" - }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/repeat-element": { - "version": "1.1.2", + "node_modules/merge-stream": { + "version": "2.0.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/repeat-string": { - "version": "1.6.1", + "node_modules/merge2": { + "version": "1.4.1", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">= 8" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "node_modules/micromatch": { + "version": "3.1.10", "dev": true, + "license": "MIT", "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" + "node": ">=0.10.0" } }, - "node_modules/request/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/require-directory": { - "version": "2.1.1", + "node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.2", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "1.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/resolve": { - "version": "1.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/mime-db": { + "version": "1.50.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", + "node_modules/mime-types": { + "version": "2.1.33", "dev": true, "license": "MIT", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "mime-db": "1.50.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/resolve-from": { - "version": "4.0.0", + "node_modules/mimic-fn": { + "version": "1.2.0", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/resolve-url": { - "version": "0.2.1", + "node_modules/mimic-response": { + "version": "1.0.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/responselike": { - "version": "1.0.2", + "node_modules/min-indent": { + "version": "1.0.1", "dev": true, "license": "MIT", - "dependencies": { - "lowercase-keys": "^1.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, + "node_modules/minimatch": { + "version": "3.0.4", + "license": "ISC", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/ret": { - "version": "0.1.15", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12" - } + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "node_modules/minimist-options": { + "version": "4.1.0", "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, "engines": { - "node": ">= 4" + "node": ">= 6" } }, - "node_modules/reusify": { - "version": "1.0.4", + "node_modules/minimist-options/node_modules/kind-of": { + "version": "6.0.3", "dev": true, "license": "MIT", "engines": { - "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.6.3", - "dev": true, + "node_modules/minipass": { + "version": "3.1.5", "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "yallist": "^4.0.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=8" } }, - "node_modules/roarr": { - "version": "2.15.4", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, + "node_modules/minipass-collect": { + "version": "1.0.2", + "license": "ISC", "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" + "minipass": "^3.0.0" }, "engines": { - "node": ">=8.0" + "node": ">= 8" } }, - "node_modules/roarr/node_modules/sprintf-js": { - "version": "1.1.2", - "dev": true, - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" + "node_modules/minipass-fetch": { + "version": "1.4.1", + "license": "MIT", + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=8" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "encoding": "^0.1.12" } }, - "node_modules/rollup-plugin-jscc": { - "version": "2.0.0", - "dev": true, - "license": "MIT", + "node_modules/minipass-flush": { + "version": "1.0.5", + "license": "ISC", "dependencies": { - "@jsbits/get-package-version": "^1.0.3", - "jscc": "^1.1.1", - "rollup-pluginutils": "^2.8.2" + "minipass": "^3.0.0" }, "engines": { - "node": ">=10.12.0" - }, - "peerDependencies": { - "rollup": ">=2" + "node": ">= 8" } }, - "node_modules/rollup-plugin-jscc/node_modules/estree-walker": { - "version": "0.6.1", - "dev": true, - "license": "MIT" - }, - "node_modules/rollup-plugin-jscc/node_modules/rollup-pluginutils": { - "version": "2.8.2", + "node_modules/minipass-json-stream": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "estree-walker": "^0.6.1" + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" } }, - "node_modules/rollup-plugin-sourcemaps": { - "version": "0.4.2", - "dev": true, - "license": "MIT", + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "license": "ISC", "dependencies": { - "rollup-pluginutils": "^2.0.1", - "source-map-resolve": "^0.5.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">=4.5.0", - "npm": ">=2.15.9" - }, - "peerDependencies": { - "rollup": ">=0.31.2" + "node": ">=8" } }, - "node_modules/rollup-plugin-string": { - "version": "3.0.0", - "dev": true, - "license": "MIT", + "node_modules/minipass-sized": { + "version": "1.0.3", + "license": "ISC", "dependencies": { - "rollup-pluginutils": "^2.4.1" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, - "peerDependencies": { - "rollup": "^2.0.0" + "engines": { + "node": ">= 8" } }, - "node_modules/rollup-plugin-typescript": { - "version": "1.0.1", + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/missionlog": { + "version": "1.6.0", "dev": true, "license": "MIT", "dependencies": { - "resolve": "^1.10.0", - "rollup-pluginutils": "^2.5.0" + "@babel/runtime": "^7.8.4", + "core-js": "^3.6.4" }, - "peerDependencies": { - "tslib": "*", - "typescript": ">=2.1.0" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/rollup-pluginutils": { - "version": "2.6.0", + "node_modules/mixin-deep": { + "version": "1.3.1", "dev": true, "license": "MIT", "dependencies": { - "estree-walker": "^0.6.0", - "micromatch": "^3.1.10" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, "engines": { - "node": ">=0.12.0" + "node": ">=0.10.0" } }, - "node_modules/run-parallel": { - "version": "1.1.10", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^1.9.0" + "is-plain-object": "^2.0.4" }, "engines": { - "npm": ">=2.0.0" + "node": ">=0.10.0" } }, - "node_modules/safe-buffer": { - "version": "5.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-regex": { - "version": "1.1.0", + "node_modules/mkdirp": { + "version": "0.5.5", "dev": true, "license": "MIT", "dependencies": { - "ret": "~0.1.10" + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, + "node_modules/mkdirp-classic": { + "version": "0.5.3", "license": "MIT" }, - "node_modules/semver": { - "version": "5.5.0", + "node_modules/mkdirp-infer-owner": { + "version": "2.0.0", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "optional": true, "dependencies": { - "type-fest": "^0.13.1" + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", + "node_modules/mkdirp-infer-owner/node_modules/mkdirp": { + "version": "1.0.4", "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "node_modules/modify-values": { + "version": "1.0.1", "dev": true, - "dependencies": { - "randombytes": "^2.1.0" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/set-blocking": { + "node_modules/ms": { "version": "2.0.0", - "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/set-value": { - "version": "2.0.0", + "node_modules/multimatch": { + "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", + "node_modules/multimatch/node_modules/array-union": { + "version": "2.1.0", "dev": true, "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/multimatch/node_modules/arrify": { + "version": "2.0.1", "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/shallow-clone/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/mute-stream": { + "version": "0.0.8", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/shebang-command": { - "version": "1.2.0", - "dev": true, + "node_modules/nan": { + "version": "2.16.0", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.1.32", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.32.tgz", + "integrity": "sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^1.0.0" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/shebang-regex": { - "version": "1.0.0", + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.2", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/shell-quote": { - "version": "1.7.2", - "dev": true, + "node_modules/napi-build-utils": { + "version": "1.0.2", "license": "MIT" }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/natural-compare": { + "version": "1.4.0", "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true + "license": "MIT" }, - "node_modules/sinon": { - "version": "7.3.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.1", - "diff": "^3.5.0", - "lolex": "^4.0.1", - "nise": "^1.4.10", - "supports-color": "^5.5.0" + "node_modules/negotiator": { + "version": "0.6.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/sinon-chai": { - "version": "3.3.0", + "node_modules/neo-async": { + "version": "2.6.2", "dev": true, - "license": "(BSD-2-Clause OR WTFPL)", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0 <8.0.0" - } + "license": "MIT" }, - "node_modules/skip-regex": { - "version": "1.0.2", + "node_modules/nice-try": { + "version": "1.0.5", "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.22.0", "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, "engines": { - "node": ">=4.2" + "node": ">=10" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, + "node_modules/node-abi/node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/slice-ansi": { - "version": "2.1.0", - "dev": true, - "license": "MIT", + "node_modules/node-abi/node_modules/semver": { + "version": "7.3.7", + "license": "ISC", "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, + "node_modules/node-abi/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/node-fetch": { + "version": "2.6.7", "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { - "node": ">=4" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true, - "engines": { - "node": "*" - } + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/snapdragon": { - "version": "0.8.2", + "node_modules/node-gyp": { + "version": "5.1.1", "dev": true, "license": "MIT", "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", + "tar": "^4.4.12", + "which": "^1.3.1" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6.0.0" } }, - "node_modules/snapdragon-node": { - "version": "2.1.1", + "node_modules/node-gyp/node_modules/chownr": { + "version": "1.1.4", "dev": true, - "license": "MIT", + "license": "ISC" + }, + "node_modules/node-gyp/node_modules/fs-minipass": { + "version": "1.2.7", + "dev": true, + "license": "ISC", "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "minipass": "^2.6.0" } }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", + "node_modules/node-gyp/node_modules/minipass": { + "version": "2.9.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", + "node_modules/node-gyp/node_modules/minizlib": { + "version": "1.3.3", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" + "minipass": "^2.9.0" } }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", + "node_modules/node-gyp/node_modules/safe-buffer": { + "version": "5.2.1", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "4.4.19", + "dev": true, + "license": "ISC", "dependencies": { - "kind-of": "^6.0.0" + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.5" } }, - "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", + "node_modules/node-gyp/node_modules/which": { + "version": "1.3.1", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "which": "bin/which" } }, - "node_modules/snapdragon-node/node_modules/kind-of": { - "version": "6.0.2", + "node_modules/node-gyp/node_modules/yallist": { + "version": "3.1.1", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/snapdragon-util": { - "version": "3.0.1", + "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-notifier": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz", + "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" + "growly": "^1.3.0", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", + "shellwords": "^0.1.1", + "uuid": "^8.3.0", + "which": "^2.0.2" } }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", + "node_modules/node-notifier/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "is-descriptor": "^0.1.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", + "node_modules/node-notifier/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dev": true, - "license": "MIT", + "optional": true, "dependencies": { - "is-extendable": "^0.1.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", + "node_modules/node-notifier/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "node_modules/node-notifier/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "optional": true, "dependencies": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" + "node": ">= 8" } }, - "node_modules/socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "node_modules/node-notifier/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/noms": { + "version": "0.0.0", "dev": true, + "license": "ISC", "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - }, - "engines": { - "node": ">= 6" + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" } }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/nopt": { + "version": "4.0.3", "dev": true, + "license": "ISC", "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" + "abbrev": "1", + "osenv": "^0.1.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "bin": { + "nopt": "bin/nopt.js" } }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/sort-keys": { - "version": "2.0.0", + "node_modules/normalize-package-data": { + "version": "2.5.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/source-map": { - "version": "0.6.1", + "node_modules/normalize-path": { + "version": "3.0.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.1", + "node_modules/normalize-url": { + "version": "6.1.0", "dev": true, "license": "MIT", - "dependencies": { - "atob": "^2.0.0", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/npm-bundled": { + "version": "1.1.2", "dev": true, + "license": "ISC", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "npm-normalize-package-bin": "^1.0.1" } }, - "node_modules/source-map-url": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/sourcemap-codec": { - "version": "1.4.4", - "dev": true, - "license": "MIT" - }, - "node_modules/spawn-sync": { - "version": "1.0.15", + "node_modules/npm-conf": { + "version": "1.1.3", "dev": true, - "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "concat-stream": "^1.4.7", - "os-shim": "^0.1.2" + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/spawn-wrap": { - "version": "2.0.0", + "node_modules/npm-install-checks": { + "version": "4.0.0", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" + "semver": "^7.1.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/spawn-wrap/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/npm-install-checks/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "semver": "^6.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.3.5", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "lru-cache": "^6.0.0" }, "bin": { - "rimraf": "bin.js" + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=10" } }, - "node_modules/spawn-wrap/node_modules/semver": { - "version": "6.3.0", + "node_modules/npm-install-checks/node_modules/yallist": { + "version": "4.0.0", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "ISC" + }, + "node_modules/npm-lifecycle": { + "version": "3.1.5", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "byline": "^5.0.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^5.0.2", + "resolve-from": "^4.0.0", + "slide": "^1.1.6", + "uid-number": "0.0.6", + "umask": "^1.1.0", + "which": "^1.3.1" } }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "2.0.2", + "node_modules/npm-lifecycle/node_modules/which": { + "version": "1.3.1", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "which": "bin/which" } }, - "node_modules/spdx-correct": { - "version": "3.1.0", + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } + "license": "ISC" }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", + "node_modules/npm-packlist": { + "version": "2.2.2", "dev": true, - "license": "CC-BY-3.0" + "license": "ISC", + "dependencies": { + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", + "node_modules/npm-pick-manifest": { + "version": "6.1.1", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.4", + "node_modules/npm-pick-manifest/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, - "license": "CC0-1.0" + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "node_modules/npm-pick-manifest/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "through": "2" + "yallist": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "node_modules/npm-pick-manifest/node_modules/npm-package-arg": { + "version": "8.1.5", "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/split-string": { - "version": "3.1.0", + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.3.5", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "extend-shallow": "^3.0.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "node_modules/npm-pick-manifest/node_modules/yallist": { + "version": "4.0.0", "dev": true, + "license": "ISC" + }, + "node_modules/npm-registry-fetch": { + "version": "9.0.0", + "dev": true, + "license": "ISC", "dependencies": { - "readable-stream": "^3.0.0" + "@npmcli/ci-detect": "^1.0.0", + "lru-cache": "^6.0.0", + "make-fetch-happen": "^8.0.9", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/split2/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/split2/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { + "version": "8.1.5", "dev": true, + "license": "ISC", "dependencies": { - "safe-buffer": "~5.2.0" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", + "node_modules/npm-registry-fetch/node_modules/semver": { + "version": "7.3.5", "dev": true, - "license": "BSD-3-Clause" + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "node_modules/npm-registry-fetch/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-run-all": { + "version": "4.1.5", "dev": true, + "license": "MIT", "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" }, "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" }, "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", "dev": true, + "license": "MIT", "dependencies": { - "minipass": "^3.1.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "engines": { - "node": ">= 8" + "node": ">=4.8" } }, - "node_modules/static-extend": { - "version": "0.1.2", + "node_modules/npm-run-path": { + "version": "2.0.2", "dev": true, "license": "MIT", "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "path-key": "^2.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", + "node_modules/nwsapi": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", + "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", "dev": true, "license": "MIT", "dependencies": { - "is-descriptor": "^0.1.0" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/string_decoder": { - "version": "0.10.31", + "node_modules/object-inspect": { + "version": "1.11.0", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/string-argv": { - "version": "0.3.1", + "node_modules/object-keys": { + "version": "1.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">=0.6.19" + "node": ">= 0.4" } }, - "node_modules/string-width": { - "version": "1.0.2", + "node_modules/object-visit": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.2", + "node_modules/object.assign": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -18111,1104 +20591,1141 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", + "node_modules/object.fromentries": { + "version": "2.0.3", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.3", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.8" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "3.0.1", + "node_modules/object.pick": { + "version": "1.3.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" } }, - "node_modules/strip-eof": { - "version": "1.0.0", + "node_modules/onetime": { + "version": "5.1.2", "dev": true, "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/open-sans-fonts": { + "version": "1.6.2", "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "Apache-2.0" }, - "node_modules/strip-json-comments": { - "version": "3.1.1", + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "opener": "bin/opener-bin.js" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "node_modules/optionator": { + "version": "0.9.1", "dev": true, + "license": "MIT", "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/sumchecker": { - "version": "3.0.1", + "node_modules/ora": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", + "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "debug": "^4.1.0" + "bl": "^5.0.0", + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "strip-ansi": "^7.0.1", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">= 8.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sumchecker/node_modules/debug": { - "version": "4.3.1", + "node_modules/ora/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, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, "engines": { - "node": ">=6.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/sumchecker/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/supports-color": { - "version": "5.5.0", + "node_modules/ora/node_modules/bl": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/table": { - "version": "5.4.6", + "node_modules/ora/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "license": "BSD-3-Clause", + "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": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/table/node_modules/ansi-regex": { - "version": "4.1.0", + "node_modules/ora/node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", + "node_modules/ora/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, - "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", + "node_modules/ora/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, - "license": "MIT", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/table/node_modules/strip-ansi": { - "version": "5.2.0", + "node_modules/ora/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/taffydb": { - "version": "2.7.3", + "node_modules/ora/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, - "license": "BSD-2-Clause" + "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/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "node_modules/ora/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" + "safe-buffer": "~5.2.0" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/task-graph-runner": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/task-graph-runner/-/task-graph-runner-1.0.3.tgz", - "integrity": "sha512-aC70bepv1j9jXX70nzolNvnHJvD4A3WtU4lQ1HEjgTS8rgnRXoUUq+xl9hZ1hKYXxVwElZXmUUMxpzDC6R0mRg==", + "node_modules/os-homedir": { + "version": "1.0.2", "dev": true, - "dependencies": { - "array-includes": "^3.0.3" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "node_modules/os-locale": { + "version": "2.1.0", "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + }, "engines": { "node": ">=4" } }, - "node_modules/temp-write": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz", - "integrity": "sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw==", + "node_modules/os-locale/node_modules/execa": { + "version": "0.7.0", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.15", - "is-stream": "^2.0.0", - "make-dir": "^3.0.0", - "temp-dir": "^1.0.0", - "uuid": "^3.3.2" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/temp-write/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==", + "node_modules/os-shim": { + "version": "0.1.3", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4.0" } }, - "node_modules/temp-write/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/os-tmpdir": { + "version": "1.0.2", "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/temp-write/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/osenv": { + "version": "0.1.5", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "ISC", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, - "node_modules/terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "node_modules/p-cancelable": { + "version": "1.1.0", "dev": true, - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "node_modules/p-each-series": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", + "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "node_modules/p-finally": { + "version": "1.0.0", "dev": true, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=4" } }, - "node_modules/test-exclude": { - "version": "6.0.0", + "node_modules/p-limit": { + "version": "1.3.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "p-try": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "node_modules/p-locate": { + "version": "2.0.0", "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, "engines": { - "node": ">=0.10" + "node": ">=4" } }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/through": { - "version": "2.3.8", - "dev": true, - "license": "MIT" - }, - "node_modules/through2": { - "version": "2.0.3", - "dev": true, + "node_modules/p-map": { + "version": "4.0.0", "license": "MIT", "dependencies": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.5", + "node_modules/p-map-series": { + "version": "2.1.0", "dev": true, "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.0.3", + "node_modules/p-pipe": { + "version": "3.1.0", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/timsort": { - "version": "0.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tmp": { - "version": "0.0.33", + "node_modules/p-queue": { + "version": "6.6.2", "dev": true, "license": "MIT", "dependencies": { - "os-tmpdir": "~1.0.2" + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" }, "engines": { - "node": ">=0.6.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", + "node_modules/p-queue/node_modules/eventemitter3": { + "version": "4.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/p-reduce": { + "version": "2.1.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/to-object-path": { - "version": "0.3.0", + "node_modules/p-timeout": { + "version": "3.2.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "p-finally": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/to-readable-stream": { + "node_modules/p-try": { "version": "1.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/to-regex": { - "version": "3.0.2", + "node_modules/p-waterfall": { + "version": "2.1.1", "dev": true, "license": "MIT", "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "p-reduce": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/to-regex-range": { - "version": "2.1.1", + "node_modules/pacote": { + "version": "11.3.5", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "@npmcli/git": "^2.1.0", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.8.2", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^2.1.4", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^11.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + }, + "bin": { + "pacote": "lib/bin.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "node_modules/pacote/node_modules/debug": { + "version": "4.3.2", "dev": true, + "license": "MIT", "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "ms": "2.1.2" }, "engines": { - "node": ">=0.8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "node_modules/pacote/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "punycode": "^2.1.1" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "node_modules/pacote/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/ts-node": { - "version": "9.0.0", + "node_modules/pacote/node_modules/make-fetch-happen": { + "version": "9.1.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "arg": "^4.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" }, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" + "node": ">= 10" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", + "node_modules/pacote/node_modules/mkdirp": { + "version": "1.0.4", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { - "node": ">=0.3.1" + "node": ">=10" } }, - "node_modules/tsconfig-paths": { - "version": "3.10.1", + "node_modules/pacote/node_modules/ms": { + "version": "2.1.2", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/pacote/node_modules/npm-package-arg": { + "version": "8.1.5", + "dev": true, + "license": "ISC", "dependencies": { - "json5": "^2.2.0", - "minimist": "^1.2.0", - "strip-bom": "^3.0.0" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/tslib": { - "version": "1.9.3", + "node_modules/pacote/node_modules/npm-registry-fetch": { + "version": "11.0.0", "dev": true, - "license": "Apache-2.0" + "license": "ISC", + "dependencies": { + "make-fetch-happen": "^9.0.1", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/tsutils": { - "version": "3.18.0", + "node_modules/pacote/node_modules/rimraf": { + "version": "3.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "tslib": "^1.8.1" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 6" + "bin": { + "rimraf": "bin.js" }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tunnel": { - "version": "0.0.6", + "node_modules/pacote/node_modules/semver": { + "version": "7.3.5", "dev": true, - "license": "MIT", - "optional": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + "node": ">=10" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "node_modules/pacote/node_modules/socks-proxy-agent": { + "version": "6.1.0", "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" }, "engines": { - "node": "*" + "node": ">= 10" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "node_modules/pacote/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", "dev": true }, - "node_modules/type-check": { - "version": "0.4.0", + "node_modules/parent-module": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "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==", + "node_modules/parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", "dev": true, + "bin": { + "parse-github-url": "cli.js" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/type-fest": { - "version": "0.8.1", + "node_modules/parse-json": { + "version": "4.0.0", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", + "node_modules/parse-path": { + "version": "4.0.3", "dev": true, "license": "MIT", "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "3.9.5", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.14.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", - "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", - "dev": true, - "engines": { - "node": "*" + "is-ssh": "^1.3.0", + "protocols": "^1.4.0", + "qs": "^6.9.4", + "query-string": "^6.13.8" } }, - "node_modules/umask": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", + "node_modules/parse-url": { + "version": "6.0.0", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-ssh": "^1.3.0", + "normalize-url": "^6.1.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" } }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true }, - "node_modules/unicode-match-property-ecmascript": { - "version": "1.0.4", + "node_modules/pascalcase": { + "version": "0.1.1", "dev": true, "license": "MIT", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "1.0.4", + "node_modules/path-dirname": { + "version": "1.0.2", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/union-value": { - "version": "1.0.0", + "node_modules/path-exists": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/union-value/node_modules/arr-union": { - "version": "3.1.0", - "dev": true, + "node_modules/path-is-absolute": { + "version": "1.0.1", "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/union-value/node_modules/extend-shallow": { + "node_modules/path-key": { "version": "2.0.1", "dev": true, "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/union-value/node_modules/set-value": { - "version": "0.4.3", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "pify": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", "dev": true, "dependencies": { - "unique-slug": "^2.0.0" + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" } }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "node_modules/pend": { + "version": "1.2.0", "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } + "license": "MIT" }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true + "node_modules/perf_hooks": { + "version": "0.0.1", + "dev": true, + "license": "MIT" }, - "node_modules/universalify": { - "version": "0.1.2", + "node_modules/perf-regexes": { + "version": "1.0.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=6.14" } }, - "node_modules/unset-value": { + "node_modules/performance-now": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/physical-cpu-count": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/picocolors": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "MIT", - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/unset-value/node_modules/has-value": { + "node_modules/pidtree": { "version": "0.3.1", "dev": true, "license": "MIT", - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", + "node_modules/pify": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "isarray": "1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" + "node_modules/pixi.js": { + "resolved": "bundles/pixi.js", + "link": true }, - "node_modules/upath": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "node_modules/pixi.js-legacy": { + "resolved": "bundles/pixi.js-legacy", + "link": true + }, + "node_modules/pkg-dir": { + "version": "4.2.0", "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, "engines": { - "node": ">=4", - "yarn": "*" + "node": ">=8" } }, - "node_modules/uri-js": { - "version": "4.2.2", + "node_modules/pkg-up": { + "version": "3.1.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/urix": { - "version": "0.1.0", + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", "dev": true, - "license": "MIT" - }, - "node_modules/url": { - "version": "0.11.0", "license": "MIT", "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/url-parse-lax": { + "node_modules/pkg-up/node_modules/locate-path": { "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "prepend-http": "^2.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "license": "MIT" - }, - "node_modules/use": { - "version": "3.1.1", + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", "dev": true, "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/util-promisify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", - "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", "dev": true, + "license": "MIT", "dependencies": { - "object.getownpropertydescriptors": "^2.0.3" + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/uuid": { - "version": "3.4.0", + "node_modules/pkg-up/node_modules/p-try": { + "version": "2.2.0", "dev": true, "license": "MIT", - "bin": { - "uuid": "bin/uuid" + "engines": { + "node": ">=6" } }, - "node_modules/v8-compile-cache": { - "version": "2.1.1", - "dev": true, - "license": "MIT" + "node_modules/pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" } }, - "node_modules/validate-npm-package-name": { - "version": "3.0.0", + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "ISC", "dependencies": { - "builtins": "^1.0.3" + "ms": "^2.1.1" } }, - "node_modules/validator": { - "version": "8.2.0", + "node_modules/portfinder/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "node_modules/pre-commit": { + "version": "1.2.2", "dev": true, - "engines": [ - "node >=0.6.0" - ], + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "cross-spawn": "^5.0.1", + "spawn-sync": "^1.0.15", + "which": "1.2.x" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "node_modules/pre-commit/node_modules/which": { + "version": "1.2.14", "dev": true, + "license": "ISC", "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, + "node_modules/prebuild-install": { + "version": "7.1.1", + "license": "MIT", "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { "node": ">=10" } }, - "node_modules/which": { - "version": "1.3.0", - "dev": true, - "license": "ISC", + "node_modules/prebuild-install/node_modules/decompress-response": { + "version": "6.0.0", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "mimic-response": "^3.1.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, + "node_modules/prebuild-install/node_modules/mimic-response": { + "version": "3.1.0", "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/wide-align": { - "version": "1.1.3", - "dev": true, - "license": "ISC", + "node_modules/prebuild-install/node_modules/simple-get": { + "version": "4.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "string-width": "^1.0.2 || 2" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/word-wrap": { - "version": "1.2.3", + "node_modules/prelude-ls": { + "version": "1.2.1", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/workerpool": { - "version": "6.1.0", + "node_modules/prepend-http": { + "version": "2.0.0", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/workspaces-run": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/workspaces-run/-/workspaces-run-1.0.1.tgz", - "integrity": "sha512-B7tZj/g4/1JCeNQ7+zVNVBC83hOJBKpOm/yYob3eqw0Aerp1Guecfdf0J6kO/I/EyA2X2uP1oCHWsh2QywXh0A==", + "node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.1", - "chalk": "^3.0.0", - "chunkd": "^2.0.1", - "cross-spawn": "^7.0.1", - "get-workspaces": "^0.5.2", - "meow": "^6.0.0", - "micromatch": "^4.0.2", - "p-limit": "^2.2.1", - "physical-cpu-count": "^2.0.0", - "redent": "^3.0.0", - "semver": "^7.1.1", - "signal-exit": "^3.0.2", - "task-graph-runner": "^1.0.3", - "trim-newlines": "^3.0.0", - "wrapline": "^2.0.1" + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" }, - "bin": { - "workspaces-run": "bin.js" + "engines": { + "node": ">= 10" } }, - "node_modules/workspaces-run/node_modules/ansi-styles": { + "node_modules/pretty-format/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/pretty-format/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==", @@ -19223,1828 +21740,6710 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/workspaces-run/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/pretty-format/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": { - "fill-range": "^7.0.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8" + "node": ">=7.0.0" } }, - "node_modules/workspaces-run/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/process-nextick-args": { + "version": "2.0.0", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/workspaces-run/node_modules/color-convert": { + "node_modules/promise-inflight": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/workspaces-run/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/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, "engines": { - "node": ">= 8" + "node": ">= 6" } }, - "node_modules/workspaces-run/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/promzard": { + "version": "0.3.0", "dev": true, + "license": "ISC", "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "read": "1" } }, - "node_modules/workspaces-run/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/proto-list": { + "version": "1.2.4", "dev": true, - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/workspaces-run/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/protocols": { + "version": "1.4.8", "dev": true, - "engines": { - "node": ">=0.12.0" + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/workspaces-run/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, - "node_modules/workspaces-run/node_modules/meow": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", - "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==", + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "^4.0.2", - "normalize-package-data": "^2.5.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.13.1", - "yargs-parser": "^18.1.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/workspaces-run/node_modules/meow/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "node_modules/punycode": { + "version": "2.1.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/workspaces-run/node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "node_modules/q": { + "version": "1.5.1", "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/workspaces-run/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/qs": { + "version": "6.10.1", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "p-try": "^2.0.0" + "side-channel": "^1.0.4" }, "engines": { - "node": ">=6" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/workspaces-run/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/workspaces-run/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==", + "node_modules/query-string": { + "version": "6.14.1", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/workspaces-run/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, + "node_modules/querystring": { + "version": "0.2.0", "engines": { - "node": ">=8" + "node": ">=0.4.x" } }, - "node_modules/workspaces-run/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/quick-lru": { + "version": "4.0.1", "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/workspaces-run/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, + "node_modules/rc": { + "version": "1.2.8", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "rc": "cli.js" } }, - "node_modules/workspaces-run/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/workspaces-run/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/read": { + "version": "1.0.7", "dev": true, + "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "mute-stream": "~0.0.4" }, "engines": { - "node": ">=10" + "node": ">=0.8" } }, - "node_modules/workspaces-run/node_modules/shebang-command": { + "node_modules/read-cmd-shim": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/workspaces-run/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/read-package-json": { + "version": "3.0.1", "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^3.0.0", + "npm-normalize-package-bin": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/workspaces-run/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/read-package-json-fast": { + "version": "2.0.3", "dev": true, + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/workspaces-run/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/read-package-json/node_modules/hosted-git-info": { + "version": "4.0.2", "dev": true, + "license": "ISC", "dependencies": { - "is-number": "^7.0.0" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=10" } }, - "node_modules/workspaces-run/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/read-package-json/node_modules/lru-cache": { + "version": "6.0.0", "dev": true, + "license": "ISC", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=10" } }, - "node_modules/workspaces-run/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "2.1.0", + "node_modules/read-package-json/node_modules/normalize-package-data": { + "version": "3.0.3", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/wrapline": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wrapline/-/wrapline-2.0.1.tgz", - "integrity": "sha1-x5kIrBX0HUAdpmB/8lZh1MkUebs=", + "node_modules/read-package-json/node_modules/semver": { + "version": "7.3.5", "dev": true, + "license": "ISC", "dependencies": { - "duplexer2": "~0.0.2", - "split2": "^0.1.2", - "through2": "^0.5.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/wrapline/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/wrapline/node_modules/split2": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-0.1.2.tgz", - "integrity": "sha1-pNVguR8EFo8hzZvdVptveNUWRZM=", + "node_modules/read-package-json/node_modules/yallist": { + "version": "4.0.0", "dev": true, - "dependencies": { - "through2": "~0.4.1" - } + "license": "ISC" }, - "node_modules/wrapline/node_modules/split2/node_modules/through2": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "node_modules/read-package-tree": { + "version": "5.3.1", "dev": true, + "license": "ISC", "dependencies": { - "readable-stream": "~1.0.17", - "xtend": "~2.1.1" + "read-package-json": "^2.0.0", + "readdir-scoped-modules": "^1.0.0", + "util-promisify": "^2.1.0" } }, - "node_modules/wrapline/node_modules/split2/node_modules/xtend": { + "node_modules/read-package-tree/node_modules/read-package-json": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/wrapline/node_modules/through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, + "license": "ISC", "dependencies": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^2.0.0", + "npm-normalize-package-bin": "^1.0.0" } }, - "node_modules/wrapline/node_modules/xtend": { + "node_modules/read-pkg": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/write": { - "version": "1.0.3", "dev": true, "license": "MIT", "dependencies": { - "mkdirp": "^0.5.1" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/write-file-atomic": { - "version": "2.4.2", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/write-json-file": { - "version": "2.3.0", + "node_modules/read-pkg-up": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "pify": "^3.0.0", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/write-pkg": { - "version": "3.2.0", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "sort-keys": "^2.0.0", - "write-json-file": "^2.2.0" + "locate-path": "^2.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/xtend": { - "version": "4.0.1", - "dev": true, + "node_modules/readable-stream": { + "version": "1.0.34", "license": "MIT", - "engines": { - "node": ">=0.4" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/y18n": { - "version": "3.2.1", - "dev": true, - "license": "ISC" - }, - "node_modules/yallist": { - "version": "2.1.2", + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", "dev": true, + "dependencies": { + "util.promisify": "^1.0.0" + }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/yargs": { - "version": "15.4.1", + "node_modules/redent": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/yargs-parser": { - "version": "18.1.3", + "node_modules/regenerator-runtime": { + "version": "0.13.7", "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/yargs-unparser": { - "version": "2.0.0", + "node_modules/regex-not": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", + "node_modules/regexpp": { + "version": "3.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.2", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", + "node_modules/repeat-string": { + "version": "1.6.1", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.0", + "node_modules/request": { + "version": "2.88.2", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, - "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "lodash": "^4.17.19" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "request": "^2.34" } }, - "node_modules/yargs/node_modules/cliui": { - "version": "6.0.0", + "node_modules/request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", "dev": true, - "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" } }, - "node_modules/yargs/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/request/node_modules/qs": { + "version": "6.5.2", "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=7.0.0" + "node": ">=0.6" } }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", + "node_modules/request/node_modules/safe-buffer": { + "version": "5.2.1", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/yargs/node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/require-directory": { + "version": "2.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/yargs/node_modules/require-main-filename": { - "version": "2.0.0", + "node_modules/require-main-filename": { + "version": "1.0.1", "dev": true, "license": "ISC" }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.2", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.17.0", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "path-parse": "^1.0.6" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.0", + "node_modules/resolve-cwd": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.0" + "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "6.2.0", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/yargs/node_modules/y18n": { - "version": "4.0.3", + "node_modules/resolve-from": { + "version": "4.0.0", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/yauzl": { - "version": "2.10.0", + "node_modules/resolve-url": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "lowercase-keys": "^1.0.0" } }, - "node_modules/yn": { - "version": "3.1.1", + "node_modules/restore-cursor": { + "version": "3.1.0", "dev": true, "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", + "node_modules/ret": { + "version": "0.1.15", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.12" } }, - "node_modules/z-schema": { - "version": "3.18.4", + "node_modules/retry": { + "version": "0.12.0", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", "dev": true, "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "2.6.3", + "dev": true, + "license": "ISC", "dependencies": { - "lodash.get": "^4.0.0", - "lodash.isequal": "^4.0.0", - "validator": "^8.0.0" + "glob": "^7.1.3" }, "bin": { - "z-schema": "bin/z-schema" - }, - "optionalDependencies": { - "commander": "^2.7.1" + "rimraf": "bin.js" } }, - "packages/accessibility": { - "name": "@pixi/accessibility", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/utils": "6.3.0" + "node_modules/roarr": { + "version": "2.15.4", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" } }, - "packages/app": { - "name": "@pixi/app", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0" - } + "node_modules/roarr/node_modules/sprintf-js": { + "version": "1.1.2", + "dev": true, + "license": "BSD-3-Clause", + "optional": true }, - "packages/basis": { - "name": "@pixi/basis", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/compressed-textures": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/runner": "6.3.0" + "node_modules/rollup": { + "version": "2.77.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz", + "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "packages/canvas/canvas-display": { - "name": "@pixi/canvas-display", - "version": "6.3.0", - "license": "MIT", + "node_modules/rollup-plugin-esbuild": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-4.9.1.tgz", + "integrity": "sha512-qn/x7Wz9p3Xnva99qcb+nopH0d2VJwVnsxJTGEg+Sh2Z3tqQl33MhOwzekVo1YTKgv+yAmosjcBRJygMfGrtLw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^4.1.1", + "debug": "^4.3.3", + "es-module-lexer": "^0.9.3", + "joycon": "^3.0.1", + "jsonc-parser": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, "peerDependencies": { - "@pixi/display": "6.3.0" + "esbuild": ">=0.10.1", + "rollup": "^1.20.0 || ^2.0.0" } }, - "packages/canvas/canvas-extract": { - "name": "@pixi/canvas-extract", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" + "node_modules/rollup-plugin-esbuild/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" } }, - "packages/canvas/canvas-graphics": { - "name": "@pixi/canvas-graphics", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0" + "node_modules/rollup-plugin-esbuild/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 + } } }, - "packages/canvas/canvas-mesh": { - "name": "@pixi/canvas-mesh", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/settings": "6.3.0" - } + "node_modules/rollup-plugin-esbuild/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true }, - "packages/canvas/canvas-particle-container": { - "name": "@pixi/canvas-particle-container", - "version": "6.3.0", + "node_modules/rollup-plugin-esbuild/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/rollup-plugin-jscc": { + "version": "2.0.0", + "dev": true, "license": "MIT", + "dependencies": { + "@jsbits/get-package-version": "^1.0.3", + "jscc": "^1.1.1", + "rollup-pluginutils": "^2.8.2" + }, + "engines": { + "node": ">=10.12.0" + }, "peerDependencies": { - "@pixi/particle-container": "6.3.0" + "rollup": ">=2" } }, - "packages/canvas/canvas-prepare": { - "name": "@pixi/canvas-prepare", - "version": "6.3.0", + "node_modules/rollup-plugin-jscc/node_modules/estree-walker": { + "version": "0.6.1", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup-plugin-jscc/node_modules/rollup-pluginutils": { + "version": "2.8.2", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/prepare": "6.3.0" + "dependencies": { + "estree-walker": "^0.6.1" } }, - "packages/canvas/canvas-renderer": { - "name": "@pixi/canvas-renderer", - "version": "6.3.0", + "node_modules/rollup-plugin-sourcemaps": { + "version": "0.4.2", + "dev": true, "license": "MIT", + "dependencies": { + "rollup-pluginutils": "^2.0.1", + "source-map-resolve": "^0.5.0" + }, + "engines": { + "node": ">=4.5.0", + "npm": ">=2.15.9" + }, "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" + "rollup": ">=0.31.2" } }, - "packages/canvas/canvas-sprite": { - "name": "@pixi/canvas-sprite", - "version": "6.3.0", + "node_modules/rollup-plugin-string": { + "version": "3.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "rollup-pluginutils": "^2.4.1" } }, - "packages/canvas/canvas-sprite-tiling": { - "name": "@pixi/canvas-sprite-tiling", - "version": "6.3.0", + "node_modules/rollup-pluginutils": { + "version": "2.6.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite-tiling": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "estree-walker": "^0.6.0", + "micromatch": "^3.1.10" } }, - "packages/canvas/canvas-text": { - "name": "@pixi/canvas-text", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/canvas-sprite": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/text": "6.3.0" + "node_modules/rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true, + "engines": { + "node": "6.* || >= 7.*" } }, - "packages/compressed-textures": { - "name": "@pixi/compressed-textures", - "version": "6.3.0", + "node_modules/run-async": { + "version": "2.4.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "node": ">=0.12.0" } }, - "packages/constants": { - "name": "@pixi/constants", - "version": "6.3.0", + "node_modules/run-parallel": { + "version": "1.1.10", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "packages/core": { - "name": "@pixi/core", - "version": "6.3.0", - "license": "MIT", + "node_modules/rxjs": { + "version": "6.6.7", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@types/offscreencanvas": "^2019.6.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/pixijs" + "tslib": "^1.9.0" }, - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/runner": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "npm": ">=2.0.0" } }, - "packages/display": { - "name": "@pixi/display", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" - } + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "packages/events": { - "name": "@pixi/events", - "version": "6.3.0", + "node_modules/safe-regex": { + "version": "1.1.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "ret": "~0.1.10" } }, - "packages/extract": { - "name": "@pixi/extract", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "node_modules/safer-buffer": { + "version": "2.1.2", + "devOptional": true, + "license": "MIT" }, - "packages/filters/filter-alpha": { - "name": "@pixi/filter-alpha", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0" + "node_modules/sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", + "dev": true, + "dependencies": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "bin": { + "sane": "src/cli.js" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "packages/filters/filter-blur": { - "name": "@pixi/filter-blur", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/settings": "6.3.0" + "node_modules/sane/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, - "packages/filters/filter-color-matrix": { - "name": "@pixi/filter-color-matrix", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0" + "node_modules/sane/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "packages/filters/filter-displacement": { - "name": "@pixi/filter-displacement", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0" + "node_modules/sane/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" } }, - "packages/filters/filter-fxaa": { - "name": "@pixi/filter-fxaa", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0" + "node_modules/sane/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "packages/filters/filter-noise": { - "name": "@pixi/filter-noise", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0" + "node_modules/sane/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "packages/graphics": { - "name": "@pixi/graphics", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" + "node_modules/sax": { + "version": "1.2.4", + "license": "ISC" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" } }, - "packages/graphics-extras": { - "name": "@pixi/graphics-extras", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0" + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true + }, + "node_modules/semver": { + "version": "5.5.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "packages/interaction": { - "name": "@pixi/interaction", - "version": "6.3.0", + "node_modules/semver-compare": { + "version": "1.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" - } + "optional": true }, - "packages/loaders": { - "name": "@pixi/loaders", - "version": "6.3.0", + "node_modules/serialize-error": { + "version": "7.0.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/utils": "6.3.0" + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/math": { - "name": "@pixi/math", - "version": "6.3.0", - "license": "MIT" - }, - "packages/math-extras": { - "name": "@pixi/math-extras", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/math": "6.3.0" + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/mesh": { - "name": "@pixi/mesh", - "version": "6.3.0", + "node_modules/set-blocking": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/set-value": { + "version": "2.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "packages/mesh-extras": { - "name": "@pixi/mesh-extras", - "version": "6.3.0", + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "packages/mixin-cache-as-bitmap": { - "name": "@pixi/mixin-cache-as-bitmap", - "version": "6.3.0", + "node_modules/shallow-clone": { + "version": "3.0.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" } }, - "packages/mixin-get-child-by-name": { - "name": "@pixi/mixin-get-child-by-name", - "version": "6.3.0", + "node_modules/shallow-clone/node_modules/kind-of": { + "version": "6.0.3", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/display": "6.3.0" + "engines": { + "node": ">=0.10.0" } }, - "packages/mixin-get-global-position": { - "name": "@pixi/mixin-get-global-position", - "version": "6.3.0", + "node_modules/shebang-command": { + "version": "1.2.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0" + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "packages/particle-container": { - "name": "@pixi/particle-container", - "version": "6.3.0", + "node_modules/shebang-regex": { + "version": "1.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "node": ">=0.10.0" } }, - "packages/polyfill": { - "name": "@pixi/polyfill", - "version": "6.3.0", + "node_modules/shell-quote": { + "version": "1.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true, + "optional": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "dev": true, "license": "MIT", "dependencies": { - "object-assign": "^4.1.1", - "promise-polyfill": "^8.2.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, - "devDependencies": { - "@types/object-assign": "^4.0.30", - "@types/promise-polyfill": "^6.0.3" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/prepare": { - "name": "@pixi/prepare", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/ticker": "6.3.0" - } + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" }, - "packages/runner": { - "name": "@pixi/runner", - "version": "6.3.0", + "node_modules/simple-concat": { + "version": "1.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "packages/settings": { - "name": "@pixi/settings", - "version": "6.3.0", + "node_modules/simple-get": { + "version": "3.1.1", "license": "MIT", "dependencies": { - "ismobilejs": "^1.1.0" + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "packages/sprite": { - "name": "@pixi/sprite", - "version": "6.3.0", + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "packages/sprite-animated": { - "name": "@pixi/sprite-animated", - "version": "6.3.0", + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/ticker": "6.3.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/sprite-tiling": { - "name": "@pixi/sprite-tiling", - "version": "6.3.0", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/skip-regex": { + "version": "1.0.2", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "node": ">=4.2" } }, - "packages/spritesheet": { - "name": "@pixi/spritesheet", - "version": "6.3.0", + "node_modules/slash": { + "version": "3.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "node": ">=8" } }, - "packages/text": { - "name": "@pixi/text", - "version": "6.3.0", + "node_modules/slice-ansi": { + "version": "2.1.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "packages/text-bitmap": { - "name": "@pixi/text-bitmap", - "version": "6.3.0", + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, "license": "MIT", - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/utils": "6.3.0" + "engines": { + "node": ">=4" } }, - "packages/ticker": { - "name": "@pixi/ticker", - "version": "6.3.0", - "license": "MIT", - "peerDependencies": { - "@pixi/settings": "6.3.0" + "node_modules/slide": { + "version": "1.1.6", + "dev": true, + "license": "ISC", + "engines": { + "node": "*" } }, - "packages/unsafe-eval": { - "name": "@pixi/unsafe-eval", - "version": "6.3.0", + "node_modules/smart-buffer": { + "version": "4.2.0", "license": "MIT", - "peerDependencies": { - "@pixi/core": "6.3.0" + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "packages/utils": { - "name": "@pixi/utils", - "version": "6.3.0", + "node_modules/snapdragon": { + "version": "0.8.2", + "dev": true, "license": "MIT", "dependencies": { - "@types/earcut": "^2.1.0", - "earcut": "^2.2.2", - "eventemitter3": "^3.1.0", - "url": "^0.11.0" - }, - "devDependencies": { - "css-color-names": "^1.0.1" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/settings": "6.3.0" + "engines": { + "node": ">=0.10.0" } }, - "tools/integration-tests": { - "name": "@internal/integration-tests", - "version": "6.3.0", - "devDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/utils": "6.3.0" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", + "node_modules/snapdragon-node": { + "version": "2.1.1", "dev": true, - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/compat-data": { - "version": "7.14.0", - "dev": true - }, - "@babel/core": { - "version": "7.14.0", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-module-transforms": "^7.14.0", - "@babel/helpers": "^7.14.0", - "@babel/parser": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, + "license": "MIT", "dependencies": { - "@babel/traverse": { - "version": "7.14.0", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "dev": true - }, - "semver": { - "version": "6.3.0", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "dev": true - } + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/generator": { - "version": "7.14.1", + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", "dev": true, - "requires": { - "@babel/types": "^7.14.1", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, + "license": "MIT", "dependencies": { - "jsesc": { - "version": "2.5.2", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "dev": true - } + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-annotate-as-pure": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz", - "integrity": "sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==", + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", "dev": true, - "requires": { - "@babel/types": "^7.15.4" + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-compilation-targets": { - "version": "7.13.16", + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", "dev": true, - "requires": { - "@babel/compat-data": "^7.13.15", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.14.5", - "semver": "^6.3.0" - }, + "license": "MIT", "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-function-name": { - "version": "7.12.13", + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.12.13" + "license": "MIT", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-get-function-arity": { - "version": "7.12.13", + "node_modules/snapdragon-node/node_modules/kind-of": { + "version": "6.0.2", "dev": true, - "requires": { - "@babel/types": "^7.12.13" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", + "node_modules/snapdragon-util": { + "version": "3.0.1", "dev": true, - "requires": { - "@babel/types": "^7.13.12" + "license": "MIT", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", "dev": true, - "requires": { - "@babel/types": "^7.15.4" + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-module-transforms": { - "version": "7.14.0", + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-simple-access": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" - }, + "license": "MIT", "dependencies": { - "@babel/traverse": { - "version": "7.14.0", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "dev": true - } + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-optimise-call-expression": { - "version": "7.12.13", + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", "dev": true, - "requires": { - "@babel/types": "^7.12.13" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true + "node_modules/socks": { + "version": "2.6.2", + "license": "MIT", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } }, - "@babel/helper-replace-supers": { - "version": "7.13.12", + "node_modules/socks-proxy-agent": { + "version": "5.0.1", "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.13.0", - "@babel/types": "^7.13.12" + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.2", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/traverse": { - "version": "7.14.0", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "dev": true + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "@babel/helper-simple-access": { - "version": "7.13.12", + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } + "license": "MIT" }, - "@babel/helper-split-export-declaration": { - "version": "7.12.13", + "node_modules/sort-keys": { + "version": "2.0.0", "dev": true, - "requires": { - "@babel/types": "^7.12.13" + "license": "MIT", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" } }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "dev": true - }, - "@babel/helpers": { - "version": "7.14.0", + "node_modules/source-map": { + "version": "0.6.1", "dev": true, - "requires": { - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" - }, - "dependencies": { + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "atob": "^2.0.0", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/sourcemap-codec": { + "version": "1.4.4", + "dev": true, + "license": "MIT" + }, + "node_modules/spawn-sync": { + "version": "1.0.15", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.2.0", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.4", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/split2/node_modules/safe-buffer": { + "version": "5.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/split2/node_modules/string_decoder": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.16.1", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "license": "MIT" + }, + "node_modules/string-argv": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "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-length/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/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "bin": { + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/sumchecker/node_modules/debug": { + "version": "4.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sumchecker/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/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/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/table": { + "version": "5.4.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/taffydb": { + "version": "2.7.3", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/tar": { + "version": "6.1.11", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/task-graph-runner": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.0.3" + } + }, + "node_modules/temp-dir": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/temp-write": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.15", + "is-stream": "^2.0.0", + "make-dir": "^3.0.0", + "temp-dir": "^1.0.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/temp-write/node_modules/is-stream": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.0.33", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "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", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-jest": { + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^26.1.0", + "json5": "2.x", + "lodash": "4.x", + "make-error": "1.x", + "mkdirp": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "jest": ">=26 <27", + "typescript": ">=3.8 <5.0" + } + }, + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.10.1", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.0", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "dev": true, + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.3.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.14.3", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-number": { + "version": "0.0.6", + "dev": true, + "license": "ISC", + "engines": { + "node": "*" + } + }, + "node_modules/umask": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/union-value": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/arr-union": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/extend-shallow": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/set-value": { + "version": "0.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "license": "ISC", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/upath": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/url": { + "version": "0.11.0", + "license": "MIT", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "license": "MIT" + }, + "node_modules/use": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/util-promisify": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node_modules/util.promisify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", + "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "for-each": "^0.3.3", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz", + "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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/wcwidth": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "1.3.0", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/workspaces-run": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.1", + "chalk": "^3.0.0", + "chunkd": "^2.0.1", + "cross-spawn": "^7.0.1", + "get-workspaces": "^0.5.2", + "meow": "^6.0.0", + "micromatch": "^4.0.2", + "p-limit": "^2.2.1", + "physical-cpu-count": "^2.0.0", + "redent": "^3.0.0", + "semver": "^7.1.1", + "signal-exit": "^3.0.2", + "task-graph-runner": "^1.0.3", + "trim-newlines": "^3.0.0", + "wrapline": "^2.0.1" + }, + "bin": { + "workspaces-run": "bin.js" + } + }, + "node_modules/workspaces-run/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/workspaces-run/node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/chalk": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/workspaces-run/node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workspaces-run/node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/workspaces-run/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workspaces-run/node_modules/meow": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "^4.0.2", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workspaces-run/node_modules/meow/node_modules/type-fest": { + "version": "0.13.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workspaces-run/node_modules/micromatch": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/workspaces-run/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workspaces-run/node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/workspaces-run/node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workspaces-run/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/read-pkg": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/read-pkg-up": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workspaces-run/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/semver": { + "version": "7.3.5", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workspaces-run/node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workspaces-run/node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/workspaces-run/node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workspaces-run/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/workspaces-run/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrapline": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "~0.0.2", + "split2": "^0.1.2", + "through2": "^0.5.1" + } + }, + "node_modules/wrapline/node_modules/object-keys": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/wrapline/node_modules/split2": { + "version": "0.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~0.4.1" + } + }, + "node_modules/wrapline/node_modules/split2/node_modules/through2": { + "version": "0.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + } + }, + "node_modules/wrapline/node_modules/split2/node_modules/xtend": { + "version": "2.1.2", + "dev": true, + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/wrapline/node_modules/through2": { + "version": "0.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "node_modules/wrapline/node_modules/xtend": { + "version": "3.0.0", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/write": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-file-atomic": { + "version": "2.4.2", + "dev": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.4.23", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.1", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.1", + "dev": true, + "license": "ISC" + }, + "node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/yargs/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/z-schema": { + "version": "5.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^2.7.1" + } + }, + "packages/accessibility": { + "name": "@pixi/accessibility", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/app": { + "name": "@pixi/app", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/assets": { + "name": "@pixi/assets", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/basis": { + "name": "@pixi/basis", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-display": { + "name": "@pixi/canvas-display", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-extract": { + "name": "@pixi/canvas-extract", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-graphics": { + "name": "@pixi/canvas-graphics", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-mesh": { + "name": "@pixi/canvas-mesh", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-particle-container": { + "name": "@pixi/canvas-particle-container", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-prepare": { + "name": "@pixi/canvas-prepare", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-renderer": { + "name": "@pixi/canvas-renderer", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-sprite": { + "name": "@pixi/canvas-sprite", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-sprite-tiling": { + "name": "@pixi/canvas-sprite-tiling", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/canvas-text": { + "name": "@pixi/canvas-text", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/compressed-textures": { + "name": "@pixi/compressed-textures", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/constants": { + "name": "@pixi/constants", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/core": { + "name": "@pixi/core", + "version": "7.0.0-alpha", + "license": "MIT", + "dependencies": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/runner": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", + "@pixi/ticker": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha", + "@types/offscreencanvas": "^2019.6.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/pixijs" + } + }, + "packages/display": { + "name": "@pixi/display", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/events": { + "name": "@pixi/events", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/extensions": { + "name": "@pixi/extensions", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/extract": { + "name": "@pixi/extract", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-alpha": { + "name": "@pixi/filter-alpha", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-blur": { + "name": "@pixi/filter-blur", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-color-matrix": { + "name": "@pixi/filter-color-matrix", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-displacement": { + "name": "@pixi/filter-displacement", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-fxaa": { + "name": "@pixi/filter-fxaa", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/filter-noise": { + "name": "@pixi/filter-noise", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/graphics": { + "name": "@pixi/graphics", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/graphics-extras": { + "name": "@pixi/graphics-extras", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/interaction": { + "version": "6.5.3", + "extraneous": true, + "license": "MIT", + "peerDependencies": { + "@pixi/core": "6.5.3", + "@pixi/display": "6.5.3", + "@pixi/math": "6.5.3", + "@pixi/ticker": "6.5.3", + "@pixi/utils": "6.5.3" + } + }, + "packages/loaders": { + "name": "@pixi/loaders", + "version": "6.5.1", + "extraneous": true, + "license": "MIT", + "peerDependencies": { + "@pixi/constants": "6.5.3", + "@pixi/core": "6.5.3", + "@pixi/utils": "6.5.3" + } + }, + "packages/math": { + "name": "@pixi/math", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/math-extras": { + "name": "@pixi/math-extras", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/mesh": { + "name": "@pixi/mesh", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/mesh-extras": { + "name": "@pixi/mesh-extras", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/mixin-cache-as-bitmap": { + "name": "@pixi/mixin-cache-as-bitmap", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/mixin-get-child-by-name": { + "name": "@pixi/mixin-get-child-by-name", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/mixin-get-global-position": { + "name": "@pixi/mixin-get-global-position", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/particle-container": { + "name": "@pixi/particle-container", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/polyfill": { + "version": "6.5.3", + "extraneous": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "promise-polyfill": "^8.2.0" + }, + "devDependencies": { + "@types/object-assign": "^4.0.30", + "@types/promise-polyfill": "^6.0.3" + } + }, + "packages/prepare": { + "name": "@pixi/prepare", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/runner": { + "name": "@pixi/runner", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/settings": { + "name": "@pixi/settings", + "version": "7.0.0-alpha", + "license": "MIT", + "devDependencies": { + "ismobilejs": "^1.1.0" + } + }, + "packages/sprite": { + "name": "@pixi/sprite", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/sprite-animated": { + "name": "@pixi/sprite-animated", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/sprite-tiling": { + "name": "@pixi/sprite-tiling", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/spritesheet": { + "name": "@pixi/spritesheet", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/text": { + "name": "@pixi/text", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/text-bitmap": { + "name": "@pixi/text-bitmap", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/ticker": { + "name": "@pixi/ticker", + "version": "7.0.0-alpha", + "license": "MIT", + "dependencies": { + "@pixi/extensions": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha" + } + }, + "packages/unsafe-eval": { + "name": "@pixi/unsafe-eval", + "version": "7.0.0-alpha", + "license": "MIT" + }, + "packages/utils": { + "name": "@pixi/utils", + "version": "7.0.0-alpha", + "license": "MIT", + "dependencies": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", + "@types/earcut": "^2.1.0", + "earcut": "^2.2.4", + "eventemitter3": "^3.1.0", + "url": "^0.11.0" + }, + "devDependencies": { + "css-color-names": "^1.0.1" + } + }, + "tools/integration-tests": { + "name": "@internal/integration-tests", + "version": "7.0.0-alpha", + "devDependencies": { + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@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, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "dev": true + }, + "@babel/core": { + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", + "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.5", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.5", + "@babel/types": "^7.18.4", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "@babel/traverse": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", + "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", + "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dev": true, + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "dependencies": { + "@babel/traverse": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", + "dev": true + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "dependencies": { + "@babel/traverse": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "dev": true, + "requires": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "dependencies": { "@babel/traverse": { - "version": "7.14.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", + "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", + "dev": true + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz", + "integrity": "sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", + "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@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, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-flow-comments": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-comments/-/plugin-transform-flow-comments-7.17.12.tgz", + "integrity": "sha512-H0hZkvKuOmBGN12CqqiiqB7uNGoYUagi8RBdR2KUuAGwGRMfM7IheYPraSX9CHQXDbSriR6QWBq0lQ9d5AKXVw==", + "dev": true, + "requires": { + "@babel/generator": "^7.17.12", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-flow": "^7.17.12" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz", + "integrity": "sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.18.6" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-react": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + } + }, + "@babel/runtime": { + "version": "7.12.5", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" + } + }, + "@babel/traverse": { + "version": "7.9.5", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.5", + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", + "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@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 + }, + "@changesets/types": { + "version": "0.4.0", + "dev": true + }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@electron/get": { + "version": "1.12.4", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^2.0.2", + "global-tunnel-ng": "^2.7.1", + "got": "^9.6.0", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "fs-extra": { + "version": "8.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "ms": { + "version": "2.1.2", + "dev": true + }, + "semver": { + "version": "6.3.0", + "dev": true + } + } + }, + "@es-joy/jsdoccomment": { + "version": "0.29.0", + "dev": true, + "requires": { + "comment-parser": "1.3.1", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "~3.0.1" + } + }, + "@fork-of/git-branch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fork-of/git-branch/-/git-branch-2.1.1.tgz", + "integrity": "sha512-X4dAtlXMGKYzOsc6W9LhKZh2m8L4KgWr6Im4gOTAhw7Mqekw8PWSGb8cetO3SVejp5gDbv0iMpd24vsks6S2TA==", + "dev": true, + "requires": { + "find-git-root": "^1.0.4" + } + }, + "@gar/promisify": { + "version": "1.1.2" + }, + "@hutson/parse-repository-url": { + "version": "3.0.2", + "dev": true + }, + "@internal/integration-tests": { + "version": "file:tools/integration-tests", + "requires": { + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "dev": true + }, + "@jest/console": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", + "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/reporters": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^26.6.2", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-resolve-dependencies": "^26.6.3", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "jest-watcher": "^26.6.2", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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 + }, + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "@jest/environment": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", + "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2" + }, + "dependencies": { + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + } + } + }, + "@jest/fake-timers": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", + "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@sinonjs/fake-timers": "^6.0.1", + "@types/node": "*", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" + }, + "dependencies": { + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + } + } + }, + "@jest/globals": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", + "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", + "dev": true, + "requires": { + "@jest/environment": "^26.6.2", + "@jest/types": "^26.6.2", + "expect": "^26.6.2" + } + }, + "@jest/reporters": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz", + "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.4", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "node-notifier": "^8.0.0", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", + "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", + "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", + "dev": true, + "requires": { + "@jest/test-result": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-runner": "^26.6.3", + "jest-runtime": "^26.6.3" + } + }, + "@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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 + }, + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@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 + }, + "@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==", + "dev": true + }, + "@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 + }, + "@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jsbits/escape-regex-str": { + "version": "1.0.3", + "dev": true + }, + "@jsbits/get-package-version": { + "version": "1.0.3", + "dev": true + }, + "@lerna/add": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/bootstrap": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/npm-conf": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "npm-package-arg": "^8.1.0", + "p-map": "^4.0.0", + "pacote": "^11.2.6", + "semver": "^7.3.4" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "@lerna/bootstrap": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/has-npm-version": "4.0.0", + "@lerna/npm-install": "4.0.0", + "@lerna/package-graph": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/rimraf-dir": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/symlink-binary": "4.0.0", + "@lerna/symlink-dependencies": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "get-port": "^5.1.1", + "multimatch": "^5.0.0", + "npm-package-arg": "^8.1.0", + "npmlog": "^4.1.2", + "p-map": "^4.0.0", + "p-map-series": "^2.1.0", + "p-waterfall": "^2.1.1", + "read-package-tree": "^5.3.1", + "semver": "^7.3.4" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "@lerna/changed": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/collect-updates": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/listable": "4.0.0", + "@lerna/output": "4.0.0" + } + }, + "@lerna/check-working-tree": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/collect-uncommitted": "4.0.0", + "@lerna/describe-ref": "4.0.0", + "@lerna/validation-error": "4.0.0" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } + } + }, + "@lerna/child-process": { + "version": "4.0.0", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "execa": "^5.0.0", + "strong-log-transformer": "^2.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.0", - "@babel/helper-function-name": "^7.12.13", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.0", - "@babel/types": "^7.14.0", - "debug": "^4.1.0", - "globals": "^11.1.0" + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@lerna/clean": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/rimraf-dir": "4.0.0", + "p-map": "^4.0.0", + "p-map-series": "^2.1.0", + "p-waterfall": "^2.1.1" + } + }, + "@lerna/cli": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/global-options": "4.0.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "dev": true + } + } + }, + "@lerna/collect-uncommitted": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "chalk": "^4.1.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@lerna/collect-updates": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/describe-ref": "4.0.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "slash": "^3.0.0" + } + }, + "@lerna/command": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/package-graph": "4.0.0", + "@lerna/project": "4.0.0", + "@lerna/validation-error": "4.0.0", + "@lerna/write-log-file": "4.0.0", + "clone-deep": "^4.0.1", + "dedent": "^0.7.0", + "execa": "^5.0.0", + "is-ci": "^2.0.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } + } + }, + "@lerna/conventional-commits": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/validation-error": "4.0.0", + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-core": "^4.2.2", + "conventional-recommended-bump": "^6.1.0", + "fs-extra": "^9.1.0", + "get-stream": "^6.0.0", + "lodash.template": "^4.5.0", + "npm-package-arg": "^8.1.0", + "npmlog": "^4.1.2", + "pify": "^5.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "get-stream": { + "version": "6.0.1", + "dev": true + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "pify": { + "version": "5.0.0", + "dev": true + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "@lerna/create": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/npm-conf": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "fs-extra": "^9.1.0", + "globby": "^11.0.2", + "init-package-json": "^2.0.2", + "npm-package-arg": "^8.1.0", + "p-reduce": "^2.1.0", + "pacote": "^11.2.6", + "pify": "^5.0.0", + "semver": "^7.3.4", + "slash": "^3.0.0", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^3.0.0", + "whatwg-url": "^8.4.0", + "yargs-parser": "20.2.4" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "pify": { + "version": "5.0.0", + "dev": true + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "dev": true + } + } + }, + "@lerna/create-symlink": { + "version": "4.0.0", + "dev": true, + "requires": { + "cmd-shim": "^4.1.0", + "fs-extra": "^9.1.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/describe-ref": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/diff": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/validation-error": "4.0.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } + } + }, + "@lerna/exec": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/profiler": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/validation-error": "4.0.0", + "p-map": "^4.0.0" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } + } + }, + "@lerna/filter-options": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/collect-updates": "4.0.0", + "@lerna/filter-packages": "4.0.0", + "dedent": "^0.7.0", + "npmlog": "^4.1.2" + } + }, + "@lerna/filter-packages": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/validation-error": "4.0.0", + "multimatch": "^5.0.0", + "npmlog": "^4.1.2" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } + } + }, + "@lerna/get-npm-exec-opts": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/get-packed": { + "version": "4.0.0", + "dev": true, + "requires": { + "fs-extra": "^9.1.0", + "ssri": "^8.0.1", + "tar": "^6.1.0" + } + }, + "@lerna/github-client": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@octokit/plugin-enterprise-rest": "^6.0.1", + "@octokit/rest": "^18.1.0", + "git-url-parse": "^11.4.4", + "npmlog": "^4.1.2" + } + }, + "@lerna/gitlab-client": { + "version": "4.0.0", + "dev": true, + "requires": { + "node-fetch": "^2.6.1", + "npmlog": "^4.1.2", + "whatwg-url": "^8.4.0" + } + }, + "@lerna/global-options": { + "version": "4.0.0", + "dev": true + }, + "@lerna/has-npm-version": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" } }, - "debug": { - "version": "4.3.1", + "semver": { + "version": "7.3.5", "dev": true, "requires": { - "ms": "2.1.2" + "lru-cache": "^6.0.0" } }, - "ms": { - "version": "2.1.2", + "yallist": { + "version": "4.0.0", "dev": true } } }, - "@babel/highlight": { - "version": "7.14.0", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.14.1", - "dev": true - }, - "@babel/plugin-syntax-jsx": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", - "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "@lerna/import": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/validation-error": "4.0.0", + "dedent": "^0.7.0", + "fs-extra": "^9.1.0", + "p-map-series": "^2.1.0" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + } } }, - "@babel/plugin-transform-react-display-name": { - "version": "7.15.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz", - "integrity": "sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q==", + "@lerna/info": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@lerna/command": "4.0.0", + "@lerna/output": "4.0.0", + "envinfo": "^7.7.4" } }, - "@babel/plugin-transform-react-jsx": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz", - "integrity": "sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==", + "@lerna/init": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-jsx": "^7.14.5", - "@babel/types": "^7.14.9" + "@lerna/child-process": "4.0.0", + "@lerna/command": "4.0.0", + "fs-extra": "^9.1.0", + "p-map": "^4.0.0", + "write-json-file": "^4.3.0" + }, + "dependencies": { + "detect-indent": { + "version": "6.1.0", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "dev": true + }, + "sort-keys": { + "version": "4.2.0", + "dev": true, + "requires": { + "is-plain-obj": "^2.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "write-json-file": { + "version": "4.3.0", + "dev": true, + "requires": { + "detect-indent": "^6.0.0", + "graceful-fs": "^4.1.15", + "is-plain-obj": "^2.0.0", + "make-dir": "^3.0.0", + "sort-keys": "^4.0.0", + "write-file-atomic": "^3.0.0" + } + } } }, - "@babel/plugin-transform-react-jsx-development": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz", - "integrity": "sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==", + "@lerna/link": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/plugin-transform-react-jsx": "^7.14.5" + "@lerna/command": "4.0.0", + "@lerna/package-graph": "4.0.0", + "@lerna/symlink-dependencies": "4.0.0", + "p-map": "^4.0.0", + "slash": "^3.0.0" } }, - "@babel/plugin-transform-react-pure-annotations": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz", - "integrity": "sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g==", + "@lerna/list": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/listable": "4.0.0", + "@lerna/output": "4.0.0" } }, - "@babel/preset-react": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.14.5.tgz", - "integrity": "sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ==", + "@lerna/listable": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-react-display-name": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.5", - "@babel/plugin-transform-react-jsx-development": "^7.14.5", - "@babel/plugin-transform-react-pure-annotations": "^7.14.5" + "@lerna/query-graph": "4.0.0", + "chalk": "^4.1.0", + "columnify": "^1.5.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "@babel/runtime": { - "version": "7.12.5", + "@lerna/log-packed": { + "version": "4.0.0", "dev": true, "requires": { - "regenerator-runtime": "^0.13.4" + "byte-size": "^7.0.0", + "columnify": "^1.5.4", + "has-unicode": "^2.0.1", + "npmlog": "^4.1.2" } }, - "@babel/template": { - "version": "7.12.13", + "@lerna/npm-conf": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" + "config-chain": "^1.1.12", + "pify": "^5.0.0" + }, + "dependencies": { + "pify": { + "version": "5.0.0", + "dev": true + } } }, - "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", + "@lerna/npm-dist-tag": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" + "@lerna/otplease": "4.0.0", + "npm-package-arg": "^8.1.0", + "npm-registry-fetch": "^9.0.0", + "npmlog": "^4.1.2" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "hosted-git-info": { + "version": "4.0.2", "dev": true, "requires": { - "ms": "2.1.2" + "lru-cache": "^6.0.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", "dev": true } } }, - "@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "@lerna/npm-install": { + "version": "4.0.0", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" + "@lerna/child-process": "4.0.0", + "@lerna/get-npm-exec-opts": "4.0.0", + "fs-extra": "^9.1.0", + "npm-package-arg": "^8.1.0", + "npmlog": "^4.1.2", + "signal-exit": "^3.0.3", + "write-pkg": "^4.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "dev": true + } + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "pify": { + "version": "4.0.1", + "dev": true + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "type-fest": { + "version": "0.4.1", + "dev": true + }, + "write-json-file": { + "version": "3.2.0", + "dev": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" + } + }, + "write-pkg": { + "version": "4.0.0", + "dev": true, + "requires": { + "sort-keys": "^2.0.0", + "type-fest": "^0.4.1", + "write-json-file": "^3.2.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true + } } }, - "@changesets/types": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/types/-/types-0.4.0.tgz", - "integrity": "sha512-TclHHKDVYQ8rJGZgVeWiF7c91yWzTTWdPagltgutelGu/Psup5PQlUq6svx7S8suj+jXcaE34yEEsfIvzXXB2Q==", - "dev": true - }, - "@electron/get": { - "version": "1.12.4", + "@lerna/npm-publish": { + "version": "4.0.0", "dev": true, "requires": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "global-agent": "^2.0.2", - "global-tunnel-ng": "^2.7.1", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" + "@lerna/otplease": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "fs-extra": "^9.1.0", + "libnpmpublish": "^4.0.0", + "npm-package-arg": "^8.1.0", + "npmlog": "^4.1.2", + "pify": "^5.0.0", + "read-package-json": "^3.0.0" }, "dependencies": { - "debug": { - "version": "4.3.1", + "hosted-git-info": { + "version": "4.0.2", "dev": true, "requires": { - "ms": "2.1.2" + "lru-cache": "^6.0.0" } }, - "ms": { - "version": "2.1.2", + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "pify": { + "version": "5.0.0", "dev": true }, "semver": { - "version": "6.3.0", + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", "dev": true } } }, - "@gar/promisify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", - "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", - "dev": true + "@lerna/npm-run-script": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "@lerna/get-npm-exec-opts": "4.0.0", + "npmlog": "^4.1.2" + } }, - "@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "dev": true + "@lerna/otplease": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/prompt": "4.0.0" + } }, - "@internal/integration-tests": { - "version": "file:tools/integration-tests", + "@lerna/output": { + "version": "4.0.0", + "dev": true, "requires": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/utils": "6.3.0" + "npmlog": "^4.1.2" } }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", + "@lerna/pack-directory": { + "version": "4.0.0", "dev": true, "requires": { - "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" + "@lerna/get-packed": "4.0.0", + "@lerna/package": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "npm-packlist": "^2.1.4", + "npmlog": "^4.1.2", + "tar": "^6.1.0", + "temp-write": "^4.0.0" + } + }, + "@lerna/package": { + "version": "4.0.0", + "dev": true, + "requires": { + "load-json-file": "^6.2.0", + "npm-package-arg": "^8.1.0", + "write-pkg": "^4.0.0" }, "dependencies": { - "resolve-from": { - "version": "5.0.0", + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "load-json-file": { + "version": "6.2.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^5.0.0", + "strip-bom": "^4.0.0", + "type-fest": "^0.6.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "dev": true + } + } + }, + "npm-package-arg": { + "version": "8.1.5", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "pify": { + "version": "4.0.1", + "dev": true + }, + "semver": { + "version": "7.3.5", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "dev": true + }, + "write-json-file": { + "version": "3.2.0", + "dev": true, + "requires": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" + } + }, + "write-pkg": { + "version": "4.0.0", + "dev": true, + "requires": { + "sort-keys": "^2.0.0", + "type-fest": "^0.4.1", + "write-json-file": "^3.2.0" + }, + "dependencies": { + "type-fest": { + "version": "0.4.1", + "dev": true + } + } + }, + "yallist": { + "version": "4.0.0", "dev": true } } }, - "@istanbuljs/nyc-config-typescript": { - "version": "1.0.1", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "dev": true - }, - "@jsbits/escape-regex-str": { - "version": "1.0.3", - "dev": true - }, - "@jsbits/get-package-version": { - "version": "1.0.3", - "dev": true - }, - "@lerna/add": { + "@lerna/package-graph": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/add/-/add-4.0.0.tgz", - "integrity": "sha512-cpmAH1iS3k8JBxNvnMqrGTTjbY/ZAiKa1ChJzFevMYY3eeqbvhsBKnBcxjRXtdrJ6bd3dCQM+ZtK+0i682Fhng==", "dev": true, "requires": { - "@lerna/bootstrap": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/npm-conf": "4.0.0", + "@lerna/prerelease-id-from-version": "4.0.0", "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", "npm-package-arg": "^8.1.0", - "p-map": "^4.0.0", - "pacote": "^11.2.6", + "npmlog": "^4.1.2", "semver": "^7.3.4" }, "dependencies": { "@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, "requires": { "npmlog": "^4.1.2" @@ -21052,8 +28451,6 @@ }, "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -21061,8 +28458,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -21070,8 +28465,6 @@ }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -21081,8 +28474,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -21090,84 +28481,26 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "@lerna/bootstrap": { + "@lerna/prerelease-id-from-version": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-4.0.0.tgz", - "integrity": "sha512-RkS7UbeM2vu+kJnHzxNRCLvoOP9yGNgkzRdy4UV2hNalD7EP41bLvRVOwRYQ7fhc2QcbhnKNdOBihYRL0LcKtw==", "dev": true, "requires": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/has-npm-version": "4.0.0", - "@lerna/npm-install": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/symlink-binary": "4.0.0", - "@lerna/symlink-dependencies": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "get-port": "^5.1.1", - "multimatch": "^5.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1", - "read-package-tree": "^5.3.1", "semver": "^7.3.4" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - } - }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -21175,258 +28508,408 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "@lerna/changed": { + "@lerna/profiler": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-4.0.0.tgz", - "integrity": "sha512-cD+KuPRp6qiPOD+BO6S6SN5cARspIaWSOqGBpGnYzLb4uWT8Vk4JzKyYtc8ym1DIwyoFXHosXt8+GDAgR8QrgQ==", "dev": true, "requires": { - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/listable": "4.0.0", - "@lerna/output": "4.0.0" + "fs-extra": "^9.1.0", + "npmlog": "^4.1.2", + "upath": "^2.0.1" } }, - "@lerna/check-working-tree": { + "@lerna/project": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-4.0.0.tgz", - "integrity": "sha512-/++bxM43jYJCshBiKP5cRlCTwSJdRSxVmcDAXM+1oUewlZJVSVlnks5eO0uLxokVFvLhHlC5kHMc7gbVFPHv6Q==", "dev": true, "requires": { - "@lerna/collect-uncommitted": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "@lerna/validation-error": "4.0.0" + "@lerna/package": "4.0.0", + "@lerna/validation-error": "4.0.0", + "cosmiconfig": "^7.0.0", + "dedent": "^0.7.0", + "dot-prop": "^6.0.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.2", + "load-json-file": "^6.2.0", + "npmlog": "^4.1.2", + "p-map": "^4.0.0", + "resolve-from": "^5.0.0", + "write-json-file": "^4.3.0" }, "dependencies": { "@lerna/validation-error": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", "dev": true, "requires": { "npmlog": "^4.1.2" } - } - } - }, - "@lerna/child-process": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-4.0.0.tgz", - "integrity": "sha512-XtCnmCT9eyVsUUHx6y/CTBYdV9g2Cr/VxyseTWBgfIur92/YKClfEtJTbOh94jRT62hlKLqSvux/UhxXVh613Q==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + }, + "cosmiconfig": { + "version": "7.0.1", "dev": true, "requires": { - "color-convert": "^2.0.1" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" } }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "detect-indent": { + "version": "6.1.0", + "dev": true + }, + "dot-prop": { + "version": "6.0.1", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "is-obj": "^2.0.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "glob-parent": { + "version": "5.1.2", "dev": true, "requires": { - "color-name": "~1.1.4" + "is-glob": "^4.0.1" } }, - "has-flag": { + "import-fresh": { + "version": "3.3.0", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "dev": true + } + } + }, + "is-glob": { + "version": "4.0.3", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-obj": { + "version": "2.0.0", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "dev": true + }, + "load-json-file": { + "version": "6.2.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^5.0.0", + "strip-bom": "^4.0.0", + "type-fest": "^0.6.0" + } + }, + "parse-json": { + "version": "5.2.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "resolve-from": { + "version": "5.0.0", + "dev": true + }, + "sort-keys": { + "version": "4.2.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "is-plain-obj": "^2.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "write-json-file": { + "version": "4.3.0", + "dev": true, + "requires": { + "detect-indent": "^6.0.0", + "graceful-fs": "^4.1.15", + "is-plain-obj": "^2.0.0", + "make-dir": "^3.0.0", + "sort-keys": "^4.0.0", + "write-file-atomic": "^3.0.0" } } } }, - "@lerna/clean": { + "@lerna/prompt": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-4.0.0.tgz", - "integrity": "sha512-uugG2iN9k45ITx2jtd8nEOoAtca8hNlDCUM0N3lFgU/b1mEQYAPRkqr1qs4FLRl/Y50ZJ41wUz1eazS+d/0osA==", "dev": true, "requires": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1" + "inquirer": "^7.3.3", + "npmlog": "^4.1.2" } }, - "@lerna/cli": { + "@lerna/publish": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-4.0.0.tgz", - "integrity": "sha512-Neaw3GzFrwZiRZv2g7g6NwFjs3er1vhraIniEs0jjVLPMNC4eata0na3GfE5yibkM/9d3gZdmihhZdZ3EBdvYA==", "dev": true, "requires": { - "@lerna/global-options": "4.0.0", - "dedent": "^0.7.0", + "@lerna/check-working-tree": "4.0.0", + "@lerna/child-process": "4.0.0", + "@lerna/collect-updates": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/describe-ref": "4.0.0", + "@lerna/log-packed": "4.0.0", + "@lerna/npm-conf": "4.0.0", + "@lerna/npm-dist-tag": "4.0.0", + "@lerna/npm-publish": "4.0.0", + "@lerna/otplease": "4.0.0", + "@lerna/output": "4.0.0", + "@lerna/pack-directory": "4.0.0", + "@lerna/prerelease-id-from-version": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/pulse-till-done": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/validation-error": "4.0.0", + "@lerna/version": "4.0.0", + "fs-extra": "^9.1.0", + "libnpmaccess": "^4.0.1", + "npm-package-arg": "^8.1.0", + "npm-registry-fetch": "^9.0.0", "npmlog": "^4.1.2", - "yargs": "^16.2.0" + "p-map": "^4.0.0", + "p-pipe": "^3.1.0", + "pacote": "^11.2.6", + "semver": "^7.3.4" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "@lerna/validation-error": { + "version": "4.0.0", "dev": true, "requires": { - "color-convert": "^2.0.1" + "npmlog": "^4.1.2" } }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "hosted-git-info": { + "version": "4.0.2", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "lru-cache": "^6.0.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "color-name": "~1.1.4" + "yallist": "^4.0.0" } }, - "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 - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "npm-package-arg": { + "version": "8.1.5", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" } }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "semver": { + "version": "7.3.5", "dev": true, "requires": { - "ansi-regex": "^5.0.1" + "lru-cache": "^6.0.0" } }, - "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==", + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "@lerna/pulse-till-done": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, + "@lerna/query-graph": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/package-graph": "4.0.0" + } + }, + "@lerna/resolve-symlink": { + "version": "4.0.0", + "dev": true, + "requires": { + "fs-extra": "^9.1.0", + "npmlog": "^4.1.2", + "read-cmd-shim": "^2.0.0" + } + }, + "@lerna/rimraf-dir": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/child-process": "4.0.0", + "npmlog": "^4.1.2", + "path-exists": "^4.0.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "path-exists": { + "version": "4.0.0", + "dev": true + }, + "rimraf": { + "version": "3.0.2", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "glob": "^7.1.3" } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + } + } + }, + "@lerna/run": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/command": "4.0.0", + "@lerna/filter-options": "4.0.0", + "@lerna/npm-run-script": "4.0.0", + "@lerna/output": "4.0.0", + "@lerna/profiler": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/timer": "4.0.0", + "@lerna/validation-error": "4.0.0", + "p-map": "^4.0.0" + }, + "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "npmlog": "^4.1.2" } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true } } }, - "@lerna/collect-uncommitted": { + "@lerna/run-lifecycle": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/npm-conf": "4.0.0", + "npm-lifecycle": "^3.1.5", + "npmlog": "^4.1.2" + } + }, + "@lerna/run-topologically": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/query-graph": "4.0.0", + "p-queue": "^6.6.2" + } + }, + "@lerna/symlink-binary": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/create-symlink": "4.0.0", + "@lerna/package": "4.0.0", + "fs-extra": "^9.1.0", + "p-map": "^4.0.0" + } + }, + "@lerna/symlink-dependencies": { + "version": "4.0.0", + "dev": true, + "requires": { + "@lerna/create-symlink": "4.0.0", + "@lerna/resolve-symlink": "4.0.0", + "@lerna/symlink-binary": "4.0.0", + "fs-extra": "^9.1.0", + "p-map": "^4.0.0", + "p-map-series": "^2.1.0" + } + }, + "@lerna/timer": { + "version": "4.0.0", + "dev": true + }, + "@lerna/version": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-4.0.0.tgz", - "integrity": "sha512-ufSTfHZzbx69YNj7KXQ3o66V4RC76ffOjwLX0q/ab//61bObJ41n03SiQEhSlmpP+gmFbTJ3/7pTe04AHX9m/g==", "dev": true, "requires": { + "@lerna/check-working-tree": "4.0.0", "@lerna/child-process": "4.0.0", + "@lerna/collect-updates": "4.0.0", + "@lerna/command": "4.0.0", + "@lerna/conventional-commits": "4.0.0", + "@lerna/github-client": "4.0.0", + "@lerna/gitlab-client": "4.0.0", + "@lerna/output": "4.0.0", + "@lerna/prerelease-id-from-version": "4.0.0", + "@lerna/prompt": "4.0.0", + "@lerna/run-lifecycle": "4.0.0", + "@lerna/run-topologically": "4.0.0", + "@lerna/validation-error": "4.0.0", "chalk": "^4.1.0", - "npmlog": "^4.1.2" + "dedent": "^0.7.0", + "load-json-file": "^6.2.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "p-map": "^4.0.0", + "p-pipe": "^3.1.0", + "p-reduce": "^2.1.0", + "p-waterfall": "^2.1.1", + "semver": "^7.3.4", + "slash": "^3.0.0", + "temp-write": "^4.0.0", + "write-json-file": "^4.3.0" }, "dependencies": { + "@lerna/validation-error": { + "version": "4.0.0", + "dev": true, + "requires": { + "npmlog": "^4.1.2" + } + }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" @@ -21434,8 +28917,6 @@ }, "chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -21444,1386 +28925,1437 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" } }, + "detect-indent": { + "version": "6.1.0", + "dev": true + }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@lerna/collect-updates": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-4.0.0.tgz", - "integrity": "sha512-bnNGpaj4zuxsEkyaCZLka9s7nMs58uZoxrRIPJ+nrmrZYp1V5rrd+7/NYTuunOhY2ug1sTBvTAxj3NZQ+JKnOw==", - "dev": true, - "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "slash": "^3.0.0" - } - }, - "@lerna/command": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/command/-/command-4.0.0.tgz", - "integrity": "sha512-LM9g3rt5FsPNFqIHUeRwWXLNHJ5NKzOwmVKZ8anSp4e1SPrv2HNc1V02/9QyDDZK/w+5POXH5lxZUI1CHaOK/A==", - "dev": true, - "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/project": "4.0.0", - "@lerna/validation-error": "4.0.0", - "@lerna/write-log-file": "4.0.0", - "clone-deep": "^4.0.1", - "dedent": "^0.7.0", - "execa": "^5.0.0", - "is-ci": "^2.0.0", - "npmlog": "^4.1.2" - }, - "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "is-plain-obj": { + "version": "2.1.0", + "dev": true + }, + "load-json-file": { + "version": "6.2.0", "dev": true, "requires": { - "npmlog": "^4.1.2" + "graceful-fs": "^4.1.15", + "parse-json": "^5.0.0", + "strip-bom": "^4.0.0", + "type-fest": "^0.6.0" } - } - } - }, - "@lerna/conventional-commits": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-4.0.0.tgz", - "integrity": "sha512-CSUQRjJHFrH8eBn7+wegZLV3OrNc0Y1FehYfYGhjLE2SIfpCL4bmfu/ViYuHh9YjwHaA+4SX6d3hR+xkeseKmw==", - "dev": true, - "requires": { - "@lerna/validation-error": "4.0.0", - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-core": "^4.2.2", - "conventional-recommended-bump": "^6.1.0", - "fs-extra": "^9.1.0", - "get-stream": "^6.0.0", - "lodash.template": "^4.5.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "pify": "^5.0.0", - "semver": "^7.3.4" - }, - "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + }, + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "npmlog": "^4.1.2" + "yallist": "^4.0.0" } }, - "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==", + "parse-json": { + "version": "5.2.0", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@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" } }, - "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 - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "semver": { + "version": "7.3.5", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "sort-keys": { + "version": "4.2.0", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "is-plain-obj": "^2.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "strip-bom": { + "version": "4.0.0", + "dev": true }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "supports-color": { + "version": "7.2.0", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "has-flag": "^4.0.0" } }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "type-fest": { + "version": "0.6.0", "dev": true }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "write-file-atomic": { + "version": "3.0.3", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "write-json-file": { + "version": "4.3.0", + "dev": true, + "requires": { + "detect-indent": "^6.0.0", + "graceful-fs": "^4.1.15", + "is-plain-obj": "^2.0.0", + "make-dir": "^3.0.0", + "sort-keys": "^4.0.0", + "write-file-atomic": "^3.0.0" + } }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "@lerna/create": { + "@lerna/write-log-file": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-4.0.0.tgz", - "integrity": "sha512-mVOB1niKByEUfxlbKTM1UNECWAjwUdiioIbRQZEeEabtjCL69r9rscIsjlGyhGWCfsdAG5wfq4t47nlDXdLLag==", "dev": true, "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "init-package-json": "^2.0.2", - "npm-package-arg": "^8.1.0", - "p-reduce": "^2.1.0", - "pacote": "^11.2.6", - "pify": "^5.0.0", - "semver": "^7.3.4", - "slash": "^3.0.0", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0", - "whatwg-url": "^8.4.0", - "yargs-parser": "20.2.4" + "npmlog": "^4.1.2", + "write-file-atomic": "^3.0.3" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "write-file-atomic": { + "version": "3.0.3", "dev": true, "requires": { - "npmlog": "^4.1.2" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } + } + } + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.9", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1" }, - "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, + "are-we-there-yet": { + "version": "2.0.0", "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" } }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "emoji-regex": { + "version": "8.0.0" }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, + "gauge": { + "version": "3.0.2", "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" } }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, + "nopt": { + "version": "5.0.0", "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "abbrev": "1" } }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", - "dev": true + "npmlog": { + "version": "5.0.1", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, + "readable-stream": { + "version": "3.6.0", "requires": { - "lru-cache": "^6.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "rimraf": { + "version": "3.0.2", + "requires": { + "glob": "^7.1.3" + } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "safe-buffer": { + "version": "5.2.1" }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "@lerna/create-symlink": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-4.0.0.tgz", - "integrity": "sha512-I0phtKJJdafUiDwm7BBlEUOtogmu8+taxq6PtIrxZbllV9hWg59qkpuIsiFp+no7nfRVuaasNYHwNUhDAVQBig==", - "dev": true, - "requires": { - "cmd-shim": "^4.1.0", - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2" - }, - "dependencies": { - "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, + "semver": { + "version": "7.3.7", "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, + "string_decoder": { + "version": "1.3.0", "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "safe-buffer": "~5.2.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "@lerna/describe-ref": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-4.0.0.tgz", - "integrity": "sha512-eTU5+xC4C5Gcgz+Ey4Qiw9nV2B4JJbMulsYJMW8QjGcGh8zudib7Sduj6urgZXUYNyhYpRs+teci9M2J8u+UvQ==", - "dev": true, - "requires": { - "@lerna/child-process": "4.0.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-4.0.0.tgz", - "integrity": "sha512-jYPKprQVg41+MUMxx6cwtqsNm0Yxx9GDEwdiPLwcUTFx+/qKCEwifKNJ1oGIPBxyEHX2PFCOjkK39lHoj2qiag==", - "dev": true, - "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/validation-error": "4.0.0", - "npmlog": "^4.1.2" - }, - "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, + "string-width": { + "version": "4.2.3", "requires": { - "npmlog": "^4.1.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "requires": { + "ansi-regex": "^5.0.1" } + }, + "yallist": { + "version": "4.0.0" } } }, - "@lerna/exec": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-4.0.0.tgz", - "integrity": "sha512-VGXtL/b/JfY84NB98VWZpIExfhLOzy0ozm/0XaS4a2SmkAJc5CeUfrhvHxxkxiTBLkU+iVQUyYEoAT0ulQ8PCw==", + "@microsoft/api-extractor": { + "version": "7.20.1", "dev": true, "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/profiler": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "p-map": "^4.0.0" + "@microsoft/api-extractor-model": "7.16.0", + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.45.1", + "@rushstack/rig-package": "0.3.8", + "@rushstack/ts-command-line": "4.10.7", + "colors": "~1.2.1", + "lodash": "~4.17.15", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "source-map": "~0.6.1", + "typescript": "~4.5.2" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } + "semver": { + "version": "7.3.2", + "dev": true + }, + "typescript": { + "version": "4.5.5", + "dev": true } } }, - "@lerna/filter-options": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-4.0.0.tgz", - "integrity": "sha512-vV2ANOeZhOqM0rzXnYcFFCJ/kBWy/3OA58irXih9AMTAlQLymWAK0akWybl++sUJ4HB9Hx12TOqaXbYS2NM5uw==", + "@microsoft/api-extractor-model": { + "version": "7.16.0", "dev": true, "requires": { - "@lerna/collect-updates": "4.0.0", - "@lerna/filter-packages": "4.0.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2" + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "~0.15.2", + "@rushstack/node-core-library": "3.45.1" } }, - "@lerna/filter-packages": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-4.0.0.tgz", - "integrity": "sha512-+4AJIkK7iIiOaqCiVTYJxh/I9qikk4XjNQLhE3kixaqgMuHl1NQ99qXRR0OZqAWB9mh8Z1HA9bM5K1HZLBTOqA==", + "@microsoft/tsdoc": { + "version": "0.13.2", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.15.2", "dev": true, "requires": { - "@lerna/validation-error": "4.0.0", - "multimatch": "^5.0.0", - "npmlog": "^4.1.2" + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "resolve": { + "version": "1.19.0", "dev": true, "requires": { - "npmlog": "^4.1.2" + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" } } } }, - "@lerna/get-npm-exec-opts": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-4.0.0.tgz", - "integrity": "sha512-yvmkerU31CTWS2c7DvmAWmZVeclPBqI7gPVr5VATUKNWJ/zmVcU4PqbYoLu92I9Qc4gY1TuUplMNdNuZTSL7IQ==", + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", "dev": true, "requires": { - "npmlog": "^4.1.2" + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" } }, - "@lerna/get-packed": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-4.0.0.tgz", - "integrity": "sha512-rfWONRsEIGyPJTxFzC8ECb3ZbsDXJbfqWYyeeQQDrJRPnEJErlltRLPLgC2QWbxFgFPsoDLeQmFHJnf0iDfd8w==", + "@nodelib/fs.scandir": { + "version": "2.1.3", "dev": true, "requires": { - "fs-extra": "^9.1.0", - "ssri": "^8.0.1", - "tar": "^6.1.0" + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" }, "dependencies": { - "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "@nodelib/fs.stat": { + "version": "2.0.3", "dev": true } } }, - "@lerna/github-client": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-4.0.0.tgz", - "integrity": "sha512-2jhsldZtTKXYUBnOm23Lb0Fx8G4qfSXF9y7UpyUgWUj+YZYd+cFxSuorwQIgk5P4XXrtVhsUesIsli+BYSThiw==", - "dev": true, - "requires": { - "@lerna/child-process": "4.0.0", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^18.1.0", - "git-url-parse": "^11.4.4", - "npmlog": "^4.1.2" - } + "@nodelib/fs.stat": { + "version": "1.1.3", + "dev": true }, - "@lerna/gitlab-client": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-4.0.0.tgz", - "integrity": "sha512-OMUpGSkeDWFf7BxGHlkbb35T7YHqVFCwBPSIR6wRsszY8PAzCYahtH3IaJzEJyUg6vmZsNl0FSr3pdA2skhxqA==", + "@nodelib/fs.walk": { + "version": "1.2.4", "dev": true, "requires": { - "node-fetch": "^2.6.1", - "npmlog": "^4.1.2", - "whatwg-url": "^8.4.0" + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" } }, - "@lerna/global-options": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-4.0.0.tgz", - "integrity": "sha512-TRMR8afAHxuYBHK7F++Ogop2a82xQjoGna1dvPOY6ltj/pEx59pdgcJfYcynYqMkFIk8bhLJJN9/ndIfX29FTQ==", + "@npmcli/ci-detect": { + "version": "1.4.0", "dev": true }, - "@lerna/has-npm-version": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-4.0.0.tgz", - "integrity": "sha512-LQ3U6XFH8ZmLCsvsgq1zNDqka0Xzjq5ibVN+igAI5ccRWNaUsE/OcmsyMr50xAtNQMYMzmpw5GVLAivT2/YzCg==", - "dev": true, + "@npmcli/fs": { + "version": "1.0.0", "requires": { - "@lerna/child-process": "4.0.0", - "semver": "^7.3.4" + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" }, "dependencies": { "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "4.0.0" } } }, - "@lerna/import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/import/-/import-4.0.0.tgz", - "integrity": "sha512-FaIhd+4aiBousKNqC7TX1Uhe97eNKf5/SC7c5WZANVWtC7aBWdmswwDt3usrzCNpj6/Wwr9EtEbYROzxKH8ffg==", + "@npmcli/git": { + "version": "2.1.0", "dev": true, "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "p-map-series": "^2.1.0" + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "npmlog": "^4.1.2" + "yallist": "^4.0.0" } }, - "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==", + "mkdirp": { + "version": "1.0.4", + "dev": true + }, + "semver": { + "version": "7.3.5", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "lru-cache": "^6.0.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "which": { + "version": "2.0.2", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "isexe": "^2.0.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "yallist": { + "version": "4.0.0", "dev": true } } }, - "@lerna/info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/info/-/info-4.0.0.tgz", - "integrity": "sha512-8Uboa12kaCSZEn4XRfPz5KU9XXoexSPS4oeYGj76s2UQb1O1GdnEyfjyNWoUl1KlJ2i/8nxUskpXIftoFYH0/Q==", + "@npmcli/installed-package-contents": { + "version": "1.0.7", "dev": true, "requires": { - "@lerna/command": "4.0.0", - "@lerna/output": "4.0.0", - "envinfo": "^7.7.4" + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" } }, - "@lerna/init": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/init/-/init-4.0.0.tgz", - "integrity": "sha512-wY6kygop0BCXupzWj5eLvTUqdR7vIAm0OgyV9WHpMYQGfs1V22jhztt8mtjCloD/O0nEe4tJhdG62XU5aYmPNQ==", - "dev": true, + "@npmcli/move-file": { + "version": "1.1.2", "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "write-json-file": "^4.3.0" + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" }, "dependencies": { - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true + "mkdirp": { + "version": "1.0.4" }, - "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==", + "rimraf": { + "version": "3.0.2", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "@npmcli/node-gyp": { + "version": "1.0.3", + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "1.3.2", + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "1.8.6", + "dev": true, + "requires": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "node-gyp": "^7.1.0", + "read-package-json-fast": "^2.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "yallist": "^4.0.0" } }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node-gyp": { + "version": "7.1.2", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "nopt": { + "version": "5.0.0", "dev": true, "requires": { - "semver": "^6.0.0" + "abbrev": "1" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "sort-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", + "rimraf": { + "version": "3.0.2", "dev": true, "requires": { - "is-plain-obj": "^2.0.0" + "glob": "^7.1.3" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "semver": { + "version": "7.3.5", "dev": true, "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "lru-cache": "^6.0.0" } }, - "write-json-file": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", + "which": { + "version": "2.0.2", "dev": true, "requires": { - "detect-indent": "^6.0.0", - "graceful-fs": "^4.1.15", - "is-plain-obj": "^2.0.0", - "make-dir": "^3.0.0", - "sort-keys": "^4.0.0", - "write-file-atomic": "^3.0.0" + "isexe": "^2.0.0" } + }, + "yallist": { + "version": "4.0.0", + "dev": true } } }, - "@lerna/link": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/link/-/link-4.0.0.tgz", - "integrity": "sha512-KlvPi7XTAcVOByfaLlOeYOfkkDcd+bejpHMCd1KcArcFTwijOwXOVi24DYomIeHvy6HsX/IUquJ4PPUJIeB4+w==", + "@octokit/auth-token": { + "version": "2.5.0", "dev": true, "requires": { - "@lerna/command": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/symlink-dependencies": "4.0.0", - "p-map": "^4.0.0", - "slash": "^3.0.0" + "@octokit/types": "^6.0.3" } }, - "@lerna/list": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/list/-/list-4.0.0.tgz", - "integrity": "sha512-L2B5m3P+U4Bif5PultR4TI+KtW+SArwq1i75QZ78mRYxPc0U/piau1DbLOmwrdqr99wzM49t0Dlvl6twd7GHFg==", + "@octokit/core": { + "version": "3.5.1", "dev": true, "requires": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/listable": "4.0.0", - "@lerna/output": "4.0.0" + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" } }, - "@lerna/listable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-4.0.0.tgz", - "integrity": "sha512-/rPOSDKsOHs5/PBLINZOkRIX1joOXUXEtyUs5DHLM8q6/RP668x/1lFhw6Dx7/U+L0+tbkpGtZ1Yt0LewCLgeQ==", + "@octokit/endpoint": { + "version": "6.0.12", "dev": true, "requires": { - "@lerna/query-graph": "4.0.0", - "chalk": "^4.1.0", - "columnify": "^1.5.4" + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "is-plain-object": { + "version": "5.0.0", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "@lerna/log-packed": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-4.0.0.tgz", - "integrity": "sha512-+dpCiWbdzgMAtpajLToy9PO713IHoE6GV/aizXycAyA07QlqnkpaBNZ8DW84gHdM1j79TWockGJo9PybVhrrZQ==", + "@octokit/graphql": { + "version": "4.8.0", "dev": true, "requires": { - "byte-size": "^7.0.0", - "columnify": "^1.5.4", - "has-unicode": "^2.0.1", - "npmlog": "^4.1.2" + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" } }, - "@lerna/npm-conf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-4.0.0.tgz", - "integrity": "sha512-uS7H02yQNq3oejgjxAxqq/jhwGEE0W0ntr8vM3EfpCW1F/wZruwQw+7bleJQ9vUBjmdXST//tk8mXzr5+JXCfw==", + "@octokit/openapi-types": { + "version": "11.2.0", + "dev": true + }, + "@octokit/plugin-enterprise-rest": { + "version": "6.0.1", + "dev": true + }, + "@octokit/plugin-paginate-rest": { + "version": "2.17.0", "dev": true, "requires": { - "config-chain": "^1.1.12", - "pify": "^5.0.0" + "@octokit/types": "^6.34.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "dev": true + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "dev": true, + "requires": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.2", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" }, "dependencies": { - "pify": { + "is-plain-object": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true } } }, - "@lerna/npm-dist-tag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-4.0.0.tgz", - "integrity": "sha512-F20sg28FMYTgXqEQihgoqSfwmq+Id3zT23CnOwD+XQMPSy9IzyLf1fFVH319vXIw6NF6Pgs4JZN2Qty6/CQXGw==", + "@octokit/request-error": { + "version": "2.1.0", "dev": true, "requires": { - "@lerna/otplease": "4.0.0", - "npm-package-arg": "^8.1.0", - "npm-registry-fetch": "^9.0.0", - "npmlog": "^4.1.2" + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.12.0", + "dev": true, + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "@octokit/types": { + "version": "6.34.0", + "dev": true, + "requires": { + "@octokit/openapi-types": "^11.2.0" + } + }, + "@pixi-build-tools/api-extractor-lerna-monorepo": { + "version": "1.1.0", + "dev": true, + "requires": { + "@lerna/project": "^4.0.0" + } + }, + "@pixi/accessibility": { + "version": "file:packages/accessibility" + }, + "@pixi/app": { + "version": "file:packages/app" + }, + "@pixi/assets": { + "version": "file:packages/assets" + }, + "@pixi/basis": { + "version": "file:packages/basis" + }, + "@pixi/canvas-display": { + "version": "file:packages/canvas-display" + }, + "@pixi/canvas-extract": { + "version": "file:packages/canvas-extract" + }, + "@pixi/canvas-graphics": { + "version": "file:packages/canvas-graphics" + }, + "@pixi/canvas-mesh": { + "version": "file:packages/canvas-mesh" + }, + "@pixi/canvas-particle-container": { + "version": "file:packages/canvas-particle-container" + }, + "@pixi/canvas-prepare": { + "version": "file:packages/canvas-prepare" + }, + "@pixi/canvas-renderer": { + "version": "file:packages/canvas-renderer" + }, + "@pixi/canvas-sprite": { + "version": "file:packages/canvas-sprite" + }, + "@pixi/canvas-sprite-tiling": { + "version": "file:packages/canvas-sprite-tiling" + }, + "@pixi/canvas-text": { + "version": "file:packages/canvas-text" + }, + "@pixi/compressed-textures": { + "version": "file:packages/compressed-textures" + }, + "@pixi/constants": { + "version": "file:packages/constants" + }, + "@pixi/core": { + "version": "file:packages/core", + "requires": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/runner": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", + "@pixi/ticker": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha", + "@types/offscreencanvas": "^2019.6.4" + } + }, + "@pixi/display": { + "version": "file:packages/display" + }, + "@pixi/eslint-config": { + "version": "4.0.1", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0" + } + }, + "@pixi/events": { + "version": "file:packages/events" + }, + "@pixi/extensions": { + "version": "file:packages/extensions" + }, + "@pixi/extract": { + "version": "file:packages/extract" + }, + "@pixi/filter-alpha": { + "version": "file:packages/filter-alpha" + }, + "@pixi/filter-blur": { + "version": "file:packages/filter-blur" + }, + "@pixi/filter-color-matrix": { + "version": "file:packages/filter-color-matrix" + }, + "@pixi/filter-displacement": { + "version": "file:packages/filter-displacement" + }, + "@pixi/filter-fxaa": { + "version": "file:packages/filter-fxaa" + }, + "@pixi/filter-noise": { + "version": "file:packages/filter-noise" + }, + "@pixi/graphics": { + "version": "file:packages/graphics" + }, + "@pixi/graphics-extras": { + "version": "file:packages/graphics-extras" + }, + "@pixi/math": { + "version": "file:packages/math" + }, + "@pixi/math-extras": { + "version": "file:packages/math-extras" + }, + "@pixi/mesh": { + "version": "file:packages/mesh" + }, + "@pixi/mesh-extras": { + "version": "file:packages/mesh-extras" + }, + "@pixi/mixin-cache-as-bitmap": { + "version": "file:packages/mixin-cache-as-bitmap" + }, + "@pixi/mixin-get-child-by-name": { + "version": "file:packages/mixin-get-child-by-name" + }, + "@pixi/mixin-get-global-position": { + "version": "file:packages/mixin-get-global-position" + }, + "@pixi/node": { + "version": "file:bundles/pixi.js-node", + "requires": { + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha", + "@types/gl": "^4.1.0", + "@types/xml2js": "^0.4.11", + "canvas": "^2.9.1", + "cross-fetch": "^3.1.5", + "gl": "^5.0.0", + "xml2js": "^0.4.23" + } + }, + "@pixi/particle-container": { + "version": "file:packages/particle-container" + }, + "@pixi/prepare": { + "version": "file:packages/prepare" + }, + "@pixi/runner": { + "version": "file:packages/runner" + }, + "@pixi/settings": { + "version": "file:packages/settings", + "requires": { + "ismobilejs": "^1.1.0" + } + }, + "@pixi/sprite": { + "version": "file:packages/sprite" + }, + "@pixi/sprite-animated": { + "version": "file:packages/sprite-animated" + }, + "@pixi/sprite-tiling": { + "version": "file:packages/sprite-tiling" + }, + "@pixi/spritesheet": { + "version": "file:packages/spritesheet" + }, + "@pixi/text": { + "version": "file:packages/text" + }, + "@pixi/text-bitmap": { + "version": "file:packages/text-bitmap" + }, + "@pixi/ticker": { + "version": "file:packages/ticker", + "requires": { + "@pixi/extensions": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha" + } + }, + "@pixi/unsafe-eval": { + "version": "file:packages/unsafe-eval" + }, + "@pixi/utils": { + "version": "file:packages/utils", + "requires": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", + "@types/earcut": "^2.1.0", + "css-color-names": "^1.0.1", + "earcut": "^2.2.4", + "eventemitter3": "^3.1.0", + "url": "^0.11.0" + } + }, + "@pixi/webdoc-template": { + "version": "1.5.3", + "dev": true, + "requires": { + "code-prettify": "^0.1.0", + "color-themes-for-google-code-prettify": "^2.0.4", + "common-path-prefix": "^3.0.0", + "fs-extra": "^9.0.1", + "klaw-sync": "^6.0.0", + "lodash": "*", + "markdown-it": "^11.0.0", + "markdown-it-highlightjs": "^3.4.0", + "missionlog": "^1.6.0", + "open-sans-fonts": "^1.6.2", + "taffydb": "^2.7.3" + } + }, + "@rollup/plugin-alias": { + "version": "3.1.1", + "dev": true, + "requires": { + "slash": "^3.0.0" + } + }, + "@rollup/plugin-commonjs": { + "version": "15.1.0", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "commondir": "^1.0.1", + "estree-walker": "^2.0.1", + "glob": "^7.1.6", + "is-reference": "^1.2.1", + "magic-string": "^0.25.7", + "resolve": "^1.17.0" }, "dependencies": { - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "estree-walker": { + "version": "2.0.1", + "dev": true }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "magic-string": { + "version": "0.25.7", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "sourcemap-codec": "^1.4.4" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "resolve": { + "version": "1.18.1", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "@lerna/npm-install": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-4.0.0.tgz", - "integrity": "sha512-aKNxq2j3bCH3eXl3Fmu4D54s/YLL9WSwV8W7X2O25r98wzrO38AUN6AB9EtmAx+LV/SP15et7Yueg9vSaanRWg==", + "@rollup/plugin-json": { + "version": "4.1.0", "dev": true, "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/get-npm-exec-opts": "4.0.0", - "fs-extra": "^9.1.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "signal-exit": "^3.0.3", - "write-pkg": "^4.0.0" + "@rollup/pluginutils": "^3.0.8" + } + }, + "@rollup/plugin-node-resolve": { + "version": "9.0.0", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.17.0" }, "dependencies": { - "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "@types/resolve": { + "version": "1.17.1", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "@types/node": "*" } }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "resolve": { + "version": "1.18.1", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" } - }, - "type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + } + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", "dev": true }, - "write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - } - }, - "write-pkg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", - "dev": true, - "requires": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "estree-walker": { + "version": "1.0.1", "dev": true } } }, - "@lerna/npm-publish": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-4.0.0.tgz", - "integrity": "sha512-vQb7yAPRo5G5r77DRjHITc9piR9gvEKWrmfCH7wkfBnGWEqu7n8/4bFQ7lhnkujvc8RXOsYpvbMQkNfkYibD/w==", + "@rushstack/node-core-library": { + "version": "3.45.1", "dev": true, "requires": { - "@lerna/otplease": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "fs-extra": "^9.1.0", - "libnpmpublish": "^4.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "pify": "^5.0.0", - "read-package-json": "^3.0.0" + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" }, "dependencies": { "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "7.0.1", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - } - }, - "pify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", - "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "version": "7.8.0", "dev": true }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "@lerna/npm-run-script": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-4.0.0.tgz", - "integrity": "sha512-Jmyh9/IwXJjOXqKfIgtxi0bxi1pUeKe5bD3S81tkcy+kyng/GNj9WSqD5ZggoNP2NP//s4CLDAtUYLdP7CU9rA==", + "@rushstack/rig-package": { + "version": "0.3.8", "dev": true, "requires": { - "@lerna/child-process": "4.0.0", - "@lerna/get-npm-exec-opts": "4.0.0", - "npmlog": "^4.1.2" + "resolve": "~1.17.0", + "strip-json-comments": "~3.1.1" } }, - "@lerna/otplease": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-4.0.0.tgz", - "integrity": "sha512-Sgzbqdk1GH4psNiT6hk+BhjOfIr/5KhGBk86CEfHNJTk9BK4aZYyJD4lpDbDdMjIV4g03G7pYoqHzH765T4fxw==", + "@rushstack/ts-command-line": { + "version": "4.10.7", "dev": true, "requires": { - "@lerna/prompt": "4.0.0" + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "colors": "~1.2.1", + "string-argv": "~0.3.1" } }, - "@lerna/output": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/output/-/output-4.0.0.tgz", - "integrity": "sha512-Un1sHtO1AD7buDQrpnaYTi2EG6sLF+KOPEAMxeUYG5qG3khTs2Zgzq5WE3dt2N/bKh7naESt20JjIW6tBELP0w==", + "@sentry/core": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.2.0.tgz", + "integrity": "sha512-9amsbB9/ePkJRgc0cVXCVW2hQUPImgTqBbnKu4frBXBza+9MBC5W3S8ZyZt2InCK22kuhNVo3z61a8mzCgXoCA==", "dev": true, "requires": { - "npmlog": "^4.1.2" + "@sentry/hub": "7.2.0", + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "tslib": "^1.9.3" } }, - "@lerna/pack-directory": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-4.0.0.tgz", - "integrity": "sha512-NJrmZNmBHS+5aM+T8N6FVbaKFScVqKlQFJNY2k7nsJ/uklNKsLLl6VhTQBPwMTbf6Tf7l6bcKzpy7aePuq9UiQ==", + "@sentry/hub": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-7.2.0.tgz", + "integrity": "sha512-uzd+GzD++Z4QopRh3AyRc4jz4AzomMnrXTOmdXgud1BH/Du9AYutVlBc5ZYwqCuJH7QPuAW3ySU3P+16UCinIg==", "dev": true, "requires": { - "@lerna/get-packed": "4.0.0", - "@lerna/package": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "npm-packlist": "^2.1.4", - "npmlog": "^4.1.2", - "tar": "^6.1.0", - "temp-write": "^4.0.0" + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "tslib": "^1.9.3" } }, - "@lerna/package": { + "@sentry/integrations": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.2.0.tgz", + "integrity": "sha512-plOD3tTEUqLpu/VNo5bE4ojSm86sYPk6PPxIBQKfKUNOMpJGSqxsLOJesVz5v/jcIW/CYXuMTHqgculovr7t/Q==", + "dev": true, + "requires": { + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "localforage": "^1.8.1", + "tslib": "^1.9.3" + } + }, + "@sentry/node": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.2.0.tgz", + "integrity": "sha512-dSI+2DrT98+eqSAv3QG3jMrq4YefBaxRbSCR9Ok7oLQW2/eskbRWH4mgYssrDXEx319SBYHh90qq/EwCOEkHtw==", + "dev": true, + "requires": { + "@sentry/core": "7.2.0", + "@sentry/hub": "7.2.0", + "@sentry/types": "7.2.0", + "@sentry/utils": "7.2.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + } + }, + "@sentry/types": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.2.0.tgz", + "integrity": "sha512-e6w62C2AmE5ULr9w/BuVaKTRpKUMGWyw4PhcBlSdDRoS47QgURGgDFIvr3VlaDwkUfCbASwSv49fDhKRX3aoew==", + "dev": true + }, + "@sentry/utils": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-uUKIsIXyb6ZXBbl/L8UwG4gy8PBXZl5pGCUFRPbns+vi0U6vtmDRDYa1A/7E17VkBJNRPVNJQr9Pq5Yd0I0MRA==", + "dev": true, + "requires": { + "@sentry/types": "7.2.0", + "tslib": "^1.9.3" + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tootallnate/once": { + "version": "1.1.2" + }, + "@types/argparse": { + "version": "1.0.38", + "dev": true + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/color-name": { + "version": "1.1.1", + "dev": true + }, + "@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "dev": true + }, + "@types/earcut": { + "version": "2.1.1" + }, + "@types/estree": { + "version": "0.0.45", + "dev": true + }, + "@types/gl": { + "version": "4.1.0" + }, + "@types/glob": { + "version": "7.1.3", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@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 + }, + "@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, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@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, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "26.0.24", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", + "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, + "requires": { + "jest-diff": "^26.0.0", + "pretty-format": "^26.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "dev": true + }, + "@types/minimist": { + "version": "1.2.2", + "dev": true + }, + "@types/node": { + "version": "12.20.24" + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "dev": true + }, + "@types/offscreencanvas": { + "version": "2019.6.4" + }, + "@types/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/package/-/package-4.0.0.tgz", - "integrity": "sha512-l0M/izok6FlyyitxiQKr+gZLVFnvxRQdNhzmQ6nRnN9dvBJWn+IxxpM+cLqGACatTnyo9LDzNTOj2Db3+s0s8Q==", + "dev": true + }, + "@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true + }, + "@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 + }, + "@types/xml2js": { + "version": "0.4.11", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", "dev": true, "requires": { - "load-json-file": "^6.2.0", - "npm-package-arg": "^8.1.0", - "write-pkg": "^4.0.0" + "@types/yargs-parser": "*" + } + }, + "@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 + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.23.0", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/type-utils": "5.23.0", + "@typescript-eslint/utils": "5.23.0", + "debug": "^4.3.2", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.2.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "load-json-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", + "debug": { + "version": "4.3.4", "dev": true, "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^5.0.0", - "strip-bom": "^4.0.0", - "type-fest": "^0.6.0" + "ms": "2.1.2" } }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "ms": { + "version": "2.1.2", "dev": true }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, - "strip-bom": { + "yallist": { "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 - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - }, - "write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", + "dev": true + } + } + }, + "@typescript-eslint/parser": { + "version": "5.23.0", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/typescript-estree": "5.23.0", + "debug": "^4.3.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", "dev": true, "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" + "ms": "2.1.2" } }, - "write-pkg": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", + "ms": { + "version": "2.1.2", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.23.0", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/visitor-keys": "5.23.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.23.0", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.23.0", + "debug": "^4.3.2", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", "dev": true, "requires": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" - }, - "dependencies": { - "type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true - } + "ms": "2.1.2" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "ms": { + "version": "2.1.2", "dev": true } } }, - "@lerna/package-graph": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-4.0.0.tgz", - "integrity": "sha512-QED2ZCTkfXMKFoTGoccwUzjHtZMSf3UKX14A4/kYyBms9xfFsesCZ6SLI5YeySEgcul8iuIWfQFZqRw+Qrjraw==", + "@typescript-eslint/types": { + "version": "5.23.0", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.23.0", "dev": true, "requires": { - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/validation-error": "4.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "semver": "^7.3.4" + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/visitor-keys": "5.23.0", + "debug": "^4.3.2", + "globby": "^11.0.4", + "is-glob": "^4.0.3", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "debug": { + "version": "4.3.4", "dev": true, "requires": { - "npmlog": "^4.1.2" + "ms": "2.1.2" } }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "is-glob": { + "version": "4.0.3", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "is-extglob": "^2.1.1" } }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - } + "ms": { + "version": "2.1.2", + "dev": true }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -22831,218 +30363,360 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "@lerna/prerelease-id-from-version": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-4.0.0.tgz", - "integrity": "sha512-GQqguzETdsYRxOSmdFZ6zDBXDErIETWOqomLERRY54f4p+tk4aJjoVdd9xKwehC9TBfIFvlRbL1V9uQGHh1opg==", + "@typescript-eslint/utils": { + "version": "5.23.0", "dev": true, "requires": { - "semver": "^7.3.4" + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.23.0", + "@typescript-eslint/types": "5.23.0", + "@typescript-eslint/typescript-estree": "5.23.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "eslint-utils": { + "version": "3.0.0", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "eslint-visitor-keys": "^2.0.0" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "eslint-visitor-keys": { + "version": "2.1.0", "dev": true } } }, - "@lerna/profiler": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-4.0.0.tgz", - "integrity": "sha512-/BaEbqnVh1LgW/+qz8wCuI+obzi5/vRE8nlhjPzdEzdmWmZXuCKyWSEzAyHOJWw1ntwMiww5dZHhFQABuoFz9Q==", + "@typescript-eslint/visitor-keys": { + "version": "5.23.0", "dev": true, "requires": { - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2", - "upath": "^2.0.1" + "@typescript-eslint/types": "5.23.0", + "eslint-visitor-keys": "^3.0.0" }, "dependencies": { - "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==", + "eslint-visitor-keys": { + "version": "3.3.0", + "dev": true + } + } + }, + "@webdoc/cli": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/cli/-/cli-2.0.0.tgz", + "integrity": "sha512-ajf4gOeiEFjqFCuAVsBRj5W25LZiMAYGTQLQhzWRbiIa/gh9aUWQqWcf6l2gS0pF58U0bSuuWoQSsV5XF/t10w==", + "dev": true, + "requires": { + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@sentry/integrations": "7.2.0", + "@sentry/node": "7.2.0", + "@webdoc/default-template": "^2.0.0", + "@webdoc/externalize": "^2.0.0", + "@webdoc/language-babel": "^2.0.0", + "@webdoc/language-parser": "^2.0.0", + "@webdoc/legacy-template": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/plugin-markdown": "^2.0.0", + "@webdoc/template-library": "^2.0.0", + "@webdoc/types": "^2.0.0", + "array.prototype.flatmap": "~1.2.3", + "fs-extra": "^9.0.1", + "globby": "11.0.0", + "gunzip-maybe": "1.4.2", + "highlight.js": "~10.7.2", + "inquirer": "9.0.0", + "lodash.merge": "4.6.2", + "markdown-it": "13.0.1", + "missionlog": "1.6.0", + "object.fromentries": "^2.0.2", + "perf_hooks": "~0.0.1", + "pkg-up": "~3.1.0", + "read-pkg-up": "~7.0.1", + "tar-stream": "2.2.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.4", + "dev": true + }, + "ansi-escapes": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", + "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "type-fest": "^1.0.2" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "ansi-regex": { + "version": "5.0.0", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "color-convert": "^2.0.1" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true - } - } - }, - "@lerna/project": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/project/-/project-4.0.0.tgz", - "integrity": "sha512-o0MlVbDkD5qRPkFKlBZsXZjoNTWPyuL58564nSfZJ6JYNmgAptnWPB2dQlAc7HWRZkmnC2fCkEdoU+jioPavbg==", - "dev": true, - "requires": { - "@lerna/package": "4.0.0", - "@lerna/validation-error": "4.0.0", - "cosmiconfig": "^7.0.0", - "dedent": "^0.7.0", - "dot-prop": "^6.0.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.2", - "load-json-file": "^6.2.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "resolve-from": "^5.0.0", - "write-json-file": "^4.3.0" - }, - "dependencies": { - "@lerna/validation-error": { + }, + "array-union": { + "version": "2.1.0", + "dev": true + }, + "braces": { + "version": "3.0.2", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "dev": true + }, + "cli-cursor": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, "requires": { - "npmlog": "^4.1.2" + "restore-cursor": "^4.0.0" } }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "cli-width": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz", + "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", "dev": true, "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "emoji-regex": { + "version": "8.0.0", "dev": true }, - "dot-prop": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", - "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", "dev": true, "requires": { - "is-obj": "^2.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "figures": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", + "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", + "dev": true, + "requires": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + } + }, + "fill-range": { + "version": "7.0.1", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" } }, + "get-caller-file": { + "version": "2.0.5", + "dev": true + }, "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "5.1.1", "dev": true, "requires": { "is-glob": "^4.0.1" } }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "globby": { + "version": "11.0.0", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "inquirer": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.0.0.tgz", + "integrity": "sha512-eYTDdTYr/YPwRenOzLZTvaJUDXDW8GQgxvzBppuXLj/kauTRLfV8bCPVbGh2staP7edrqL+rGwjaOa+JVxBWsg==", + "dev": true, + "requires": { + "ansi-escapes": "^5.0.0", + "chalk": "^5.0.1", + "cli-cursor": "^4.0.0", + "cli-width": "^4.0.0", + "external-editor": "^3.0.3", + "figures": "^4.0.1", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^6.1.0", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^5.1.2", + "strip-ansi": "^7.0.1", + "through": "^2.3.6", + "wrap-ansi": "^8.0.1" }, "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "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 + }, + "ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true + }, + "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 + }, + "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, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.0.1.tgz", + "integrity": "sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } } } }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "version": "4.0.1", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "is-number": { + "version": "7.0.0", "dev": true }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } }, - "load-json-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", "dev": true, "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^5.0.0", - "strip-bom": "^4.0.0", - "type-fest": "^0.6.0" + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "micromatch": { + "version": "4.0.2", "dev": true, "requires": { - "semver": "^6.0.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -23051,481 +30725,739 @@ "lines-and-columns": "^1.1.6" } }, - "path-type": { + "read-pkg": { + "version": "5.2.0", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "restore-cursor": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "string-width": { + "version": "4.2.0", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", "dev": true }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "dev": true + } + } + }, + "@webdoc/default-template": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/default-template/-/default-template-2.0.0.tgz", + "integrity": "sha512-Uo8hibY6lXvw53qdlId9gY2bXWLPKSP1Kff+3uBCjdWICzH34ZIjYvNwWOZjIzroI230iHKS5HY/ythiVfNaiQ==", + "dev": true, + "requires": { + "@babel/core": "7.18.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@babel/preset-react": "^7.10.1", + "@webdoc/model": "^2.0.0", + "@webdoc/template-library": "^2.0.0", + "@webdoc/types": "^2.0.0", + "code-prettify": "^0.1.0", + "fs-extra": "^9.0.1", + "highlight.js": "~10.7.2", + "markdown-it": "13.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "sort-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true + }, + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + } + } + }, + "@webdoc/externalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/externalize/-/externalize-2.0.0.tgz", + "integrity": "sha512-q47axWF396LI8VCwtKP/Ao2M2q6UGeiSiLoErwulCJiPUJRKgE0kO9caOeydGWfxPiELvKRACJ3Bg2VVqmLgPg==", + "dev": true, + "requires": { + "@babel/core": "7.18.5", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20" + } + }, + "@webdoc/language-babel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/language-babel/-/language-babel-2.0.0.tgz", + "integrity": "sha512-IxUZlZ0pJJ0yuUMpF5WAjabHzWXX7aDhXbOC0KkZiVyDkzgqjeK1q/Ao7nqlYQlhHewYlbIM50ShX0fAGYFMLg==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/language-library": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" + }, + "dependencies": { + "@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@webdoc/language-library": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/language-library/-/language-library-2.0.0.tgz", + "integrity": "sha512-btV+hhSlO0EvPMRFrBHepp1ayQEvgKxJJu9RkF3CsTI1D8/BGr5cja0+Q+ndNXWKvTDVzpG68o3uGwQg4NdujA==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" + }, + "dependencies": { + "@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@webdoc/language-parser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/language-parser/-/language-parser-2.0.0.tgz", + "integrity": "sha512-vZUcqILH2Itgq/rF02FqrMlJcTNi+k9Vj2sxURXFlhvmPKa+jx4ErfPdrrHGxI+TbUPVinRgVZzECuuOSP4P1g==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@babel/traverse": "7.9.5", + "@babel/types": "7.9.5", + "@webdoc/language-library": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16" + }, + "dependencies": { + "@babel/types": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", "dev": true, "requires": { - "is-plain-obj": "^2.0.0" + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" } + } + } + }, + "@webdoc/legacy-template": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/legacy-template/-/legacy-template-2.0.0.tgz", + "integrity": "sha512-aNGS8HFm2gAkOEY4rxNaYLj5Fo/pVVPG8Gu+noN3AuzyCKBkLeqWZzbeJr5WElhIUvzekBiy7/D/S7TSPaKLDg==", + "dev": true, + "requires": { + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/model": "^2.0.0", + "@webdoc/template-library": "^2.0.0", + "bluebird": "^3.7.2", + "code-prettify": "^0.1.0", + "color-themes-for-google-code-prettify": "^2.0.4", + "common-path-prefix": "^3.0.0", + "escape-string-regexp": "^3.0.0", + "fs-extra": "^9.0.1", + "klaw-sync": "6.0.0", + "lodash": "^4.17.20", + "markdown-it": "13.0.1", + "markdown-it-highlightjs": "^3.1.0", + "missionlog": "1.6.0", + "open-sans-fonts": "^1.6.2" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "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==", + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "dev": true }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "escape-string-regexp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-3.0.0.tgz", + "integrity": "sha512-11dXIUC3umvzEViLP117d0KN6LJzZxh5+9F4E/7WLAAw7GrHk8NpUR+g9iJi/pe9C0py4F8rs0hreyRCwlAuZg==", "dev": true }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "uc.micro": "^1.0.1" } }, - "write-json-file": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", "dev": true, "requires": { - "detect-indent": "^6.0.0", - "graceful-fs": "^4.1.15", - "is-plain-obj": "^2.0.0", - "make-dir": "^3.0.0", - "sort-keys": "^4.0.0", - "write-file-atomic": "^3.0.0" + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" } } } }, - "@lerna/prompt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-4.0.0.tgz", - "integrity": "sha512-4Ig46oCH1TH5M7YyTt53fT6TuaKMgqUUaqdgxvp6HP6jtdak6+amcsqB8YGz2eQnw/sdxunx84DfI9XpoLj4bQ==", + "@webdoc/model": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/model/-/model-2.0.0.tgz", + "integrity": "sha512-OtyW4kigvXN9JaqAOh8S1zbRP1K1eEKP5WEi12eGfKQNmZNWhyMLxlriEbaGneX8hQWaM2uM2FMo5+nEl3oHmg==", "dev": true, "requires": { - "inquirer": "^7.3.3", - "npmlog": "^4.1.2" + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@webdoc/types": "^2.0.0", + "catharsis": "0.8.11", + "nanoid": "~3.1.16", + "taffydb": "2.7.3" } }, - "@lerna/publish": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-4.0.0.tgz", - "integrity": "sha512-K8jpqjHrChH22qtkytA5GRKIVFEtqBF6JWj1I8dWZtHs4Jywn8yB1jQ3BAMLhqmDJjWJtRck0KXhQQKzDK2UPg==", + "@webdoc/plugin-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/plugin-markdown/-/plugin-markdown-2.0.0.tgz", + "integrity": "sha512-bxbVpj7HSoUocj65FeU54DgL3mbzA0S2ird5LknOqO1gfQYn2ESVw46mwgeVyGZ46+nxWEMi6/53MOJbouor1Q==", "dev": true, "requires": { - "@lerna/check-working-tree": "4.0.0", - "@lerna/child-process": "4.0.0", - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "@lerna/log-packed": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/npm-dist-tag": "4.0.0", - "@lerna/npm-publish": "4.0.0", - "@lerna/otplease": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/pack-directory": "4.0.0", - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "@lerna/version": "4.0.0", - "fs-extra": "^9.1.0", - "libnpmaccess": "^4.0.1", - "npm-package-arg": "^8.1.0", - "npm-registry-fetch": "^9.0.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-pipe": "^3.1.0", - "pacote": "^11.2.6", - "semver": "^7.3.4" + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "highlight.js": "~10.7.2", + "markdown-it": "13.0.1" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "uc.micro": "^1.0.1" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "@lerna/pulse-till-done": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-4.0.0.tgz", - "integrity": "sha512-Frb4F7QGckaybRhbF7aosLsJ5e9WuH7h0KUkjlzSByVycxY91UZgaEIVjS2oN9wQLrheLMHl6SiFY0/Pvo0Cxg==", + "@webdoc/template-library": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/template-library/-/template-library-2.0.0.tgz", + "integrity": "sha512-71lmtpsQXPLXeyggWM9yCoGP8LkXVyLyGlnMclgsEXGTZWyeueg+GlwbUGPuJWW9WSSQS1KKevbDSapQwpt9rQ==", "dev": true, "requires": { - "npmlog": "^4.1.2" + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12", + "@fork-of/git-branch": "2.1.1", + "@webdoc/externalize": "^2.0.0", + "@webdoc/model": "^2.0.0", + "@webdoc/types": "^2.0.0", + "catharsis": "0.8.11", + "fs-extra": "^9.0.1", + "lodash": "^4.17.20", + "missionlog": "1.6.0", + "nanoid": "~3.1.16", + "node-fetch": "~2.6.1", + "parse-github-url": "1.0.2" } }, - "@lerna/query-graph": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-4.0.0.tgz", - "integrity": "sha512-YlP6yI3tM4WbBmL9GCmNDoeQyzcyg1e4W96y/PKMZa5GbyUvkS2+Jc2kwPD+5KcXou3wQZxSPzR3Te5OenaDdg==", + "@webdoc/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@webdoc/types/-/types-2.0.0.tgz", + "integrity": "sha512-QfyP46Et1PXk8Bb6IAEX8EuGbSJXPKFsP43866Dt+TW+FiTnvnU8ISQGyMPFNfmGQuCii2CWZfcbttaye/xmFA==", "dev": true, "requires": { - "@lerna/package-graph": "4.0.0" + "@babel/plugin-proposal-class-properties": "7.17.12", + "@babel/plugin-transform-flow-comments": "7.17.12" } }, - "@lerna/resolve-symlink": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-4.0.0.tgz", - "integrity": "sha512-RtX8VEUzqT+uLSCohx8zgmjc6zjyRlh6i/helxtZTMmc4+6O4FS9q5LJas2uGO2wKvBlhcD6siibGt7dIC3xZA==", + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "abbrev": { + "version": "1.1.1" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "requires": { - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2", - "read-cmd-shim": "^2.0.0" + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" }, "dependencies": { - "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true } } }, - "@lerna/rimraf-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-4.0.0.tgz", - "integrity": "sha512-QNH9ABWk9mcMJh2/muD9iYWBk1oQd40y6oH+f3wwmVGKYU5YJD//+zMiBI13jxZRtwBx0vmBZzkBkK1dR11cBg==", - "dev": true, + "acorn-jsx": { + "version": "5.2.0", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "add-stream": { + "version": "1.0.0", + "dev": true + }, + "agent-base": { + "version": "6.0.2", "requires": { - "@lerna/child-process": "4.0.0", - "npmlog": "^4.1.2", - "path-exists": "^4.0.0", - "rimraf": "^3.0.2" + "debug": "4" }, "dependencies": { - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, + "debug": { + "version": "4.3.2", "requires": { - "glob": "^7.1.3" + "ms": "2.1.2" } + }, + "ms": { + "version": "2.1.2" } } }, - "@lerna/run": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run/-/run-4.0.0.tgz", - "integrity": "sha512-9giulCOzlMPzcZS/6Eov6pxE9gNTyaXk0Man+iCIdGJNMrCnW7Dme0Z229WWP/UoxDKg71F2tMsVVGDiRd8fFQ==", - "dev": true, + "agentkeepalive": { + "version": "4.1.4", "requires": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/npm-run-script": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/profiler": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/timer": "4.0.0", - "@lerna/validation-error": "4.0.0", - "p-map": "^4.0.0" + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, + "debug": { + "version": "4.3.2", "requires": { - "npmlog": "^4.1.2" + "ms": "2.1.2" } + }, + "ms": { + "version": "2.1.2" } } }, - "@lerna/run-lifecycle": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-4.0.0.tgz", - "integrity": "sha512-IwxxsajjCQQEJAeAaxF8QdEixfI7eLKNm4GHhXHrgBu185JcwScFZrj9Bs+PFKxwb+gNLR4iI5rpUdY8Y0UdGQ==", - "dev": true, + "aggregate-error": { + "version": "3.1.0", "requires": { - "@lerna/npm-conf": "4.0.0", - "npm-lifecycle": "^3.1.5", - "npmlog": "^4.1.2" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" } }, - "@lerna/run-topologically": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-4.0.0.tgz", - "integrity": "sha512-EVZw9hGwo+5yp+VL94+NXRYisqgAlj0jWKWtAIynDCpghRxCE5GMO3xrQLmQgqkpUl9ZxQFpICgYv5DW4DksQA==", + "ajv": { + "version": "6.12.6", "dev": true, "requires": { - "@lerna/query-graph": "4.0.0", - "p-queue": "^6.6.2" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "@lerna/symlink-binary": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-4.0.0.tgz", - "integrity": "sha512-zualodWC4q1QQc1pkz969hcFeWXOsVYZC5AWVtAPTDfLl+TwM7eG/O6oP+Rr3fFowspxo6b1TQ6sYfDV6HXNWA==", + "ansi-escapes": { + "version": "4.3.2", "dev": true, "requires": { - "@lerna/create-symlink": "4.0.0", - "@lerna/package": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0" + "type-fest": "^0.21.3" }, "dependencies": { - "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, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "type-fest": { + "version": "0.21.3", "dev": true } } }, - "@lerna/symlink-dependencies": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-4.0.0.tgz", - "integrity": "sha512-BABo0MjeUHNAe2FNGty1eantWp8u83BHSeIMPDxNq0MuW2K3CiQRaeWT3EGPAzXpGt0+hVzBrA6+OT0GPn7Yuw==", + "ansi-regex": { + "version": "2.1.1" + }, + "ansi-styles": { + "version": "3.2.1", "dev": true, "requires": { - "@lerna/create-symlink": "4.0.0", - "@lerna/resolve-symlink": "4.0.0", - "@lerna/symlink-binary": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0" + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0" + }, + "are-we-there-yet": { + "version": "1.1.5", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" }, "dependencies": { - "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==", + "isarray": { + "version": "1.0.0", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "string_decoder": { + "version": "1.1.1", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "safe-buffer": "~5.1.0" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, - "@lerna/timer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-4.0.0.tgz", - "integrity": "sha512-WFsnlaE7SdOvjuyd05oKt8Leg3ENHICnvX3uYKKdByA+S3g+TCz38JsNs7OUZVt+ba63nC2nbXDlUnuT2Xbsfg==", + "arg": { + "version": "4.1.3", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "dev": true + }, + "array-differ": { + "version": "3.0.0", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==", + "dev": true + }, + "array-ify": { + "version": "1.0.0", + "dev": true + }, + "array-includes": { + "version": "3.1.3", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "1.0.2", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "dev": true + }, + "array.prototype.flatmap": { + "version": "1.2.4", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + } + }, + "arrify": { + "version": "1.0.1", + "dev": true + }, + "asap": { + "version": "2.0.6", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", "dev": true }, - "@lerna/validation-error": { - "version": "3.13.0", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } + "atob": { + "version": "2.1.2", + "dev": true }, - "@lerna/version": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/version/-/version-4.0.0.tgz", - "integrity": "sha512-otUgiqs5W9zGWJZSCCMRV/2Zm2A9q9JwSDS7s/tlKq4mWCYriWo7+wsHEA/nPTMDyYyBO5oyZDj+3X50KDUzeA==", + "aws-sign2": { + "version": "0.7.0", + "dev": true + }, + "aws4": { + "version": "1.11.0", + "dev": true + }, + "babel-jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", + "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", "dev": true, "requires": { - "@lerna/check-working-tree": "4.0.0", - "@lerna/child-process": "4.0.0", - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/conventional-commits": "4.0.0", - "@lerna/github-client": "4.0.0", - "@lerna/gitlab-client": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "chalk": "^4.1.0", - "dedent": "^0.7.0", - "load-json-file": "^6.2.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-pipe": "^3.1.0", - "p-reduce": "^2.1.0", - "p-waterfall": "^2.1.1", - "semver": "^7.3.4", - "slash": "^3.0.0", - "temp-write": "^4.0.0", - "write-json-file": "^4.3.0" + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" }, "dependencies": { - "@lerna/validation-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-4.0.0.tgz", - "integrity": "sha512-1rBOM5/koiVWlRi3V6dB863E1YzJS8v41UtsHgMr6gB2ncJ2LsQtMKlJpi3voqcgh41H8UsPXR58RrrpPpufyw==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -23554,1580 +31486,1945 @@ "color-name": "~1.1.4" } }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "load-json-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", - "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^5.0.0", - "strip-bom": "^4.0.0", - "type-fest": "^0.6.0" + "has-flag": "^4.0.0" } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + } + } + }, + "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, + "requires": { + "@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" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", "dev": true, "requires": { - "yallist": "^4.0.0" + "@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" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", + "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "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, + "requires": { + "@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" + } + }, + "babel-preset-jest": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", + "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^26.6.2", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.0" + }, + "base": { + "version": "0.11.2", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", "dev": true, "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "is-descriptor": "^1.0.0" } }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "is-accessor-descriptor": { + "version": "1.0.0", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "kind-of": "^6.0.0" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "is-data-descriptor": { + "version": "1.0.0", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "kind-of": "^6.0.0" } }, - "sort-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", - "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", + "is-descriptor": { + "version": "1.0.2", "dev": true, "requires": { - "is-plain-obj": "^2.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, - "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==", + "kind-of": { + "version": "6.0.2", "dev": true + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "before-after-hook": { + "version": "2.2.2", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bit-twiddle": { + "version": "1.0.2" + }, + "bl": { + "version": "4.1.0", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "safe-buffer": { + "version": "5.2.1" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "boolean": { + "version": "3.0.2", + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", "dev": true, "requires": { - "has-flag": "^4.0.0" + "is-extendable": "^0.1.0" } - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + } + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, + "browserslist": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz", + "integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001366", + "electron-to-chromium": "^1.4.188", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.4" + } + }, + "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, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "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, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "dev": true + }, + "byline": { + "version": "5.0.0", + "dev": true + }, + "byte-size": { + "version": "7.0.1", + "dev": true + }, + "cacache": { + "version": "15.3.0", + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "requires": { + "yallist": "^4.0.0" + } }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "mkdirp": { + "version": "1.0.4" + }, + "rimraf": { + "version": "3.0.2", + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "4.0.0" + } + } + }, + "cache-base": { + "version": "1.0.1", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cacheable-request": { + "version": "6.1.0", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", "dev": true, "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "pump": "^3.0.0" } }, - "write-json-file": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", + "lowercase-keys": { + "version": "2.0.0", + "dev": true + }, + "normalize-url": { + "version": "4.5.0", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.2", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "dependencies": { + "map-obj": { + "version": "4.3.0", + "dev": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30001369", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001369.tgz", + "integrity": "sha512-OY1SBHaodJc4wflDIKnlkdqWzJZd1Ls/2zbVJHBSv3AT7vgOJ58yAhd2CN4d57l2kPJrgMb7P9+N1Mhy4tNSQA==", + "dev": true + }, + "canvas": { + "version": "2.9.1", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.15.0", + "simple-get": "^3.0.3" + } + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "dev": true + }, + "catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "chalk": { + "version": "2.4.2", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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 + }, + "chardet": { + "version": "0.7.0", + "dev": true + }, + "chownr": { + "version": "2.0.0" + }, + "chunkd": { + "version": "2.0.1", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "dev": true + }, + "cjs-module-lexer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", + "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "arr-union": { + "version": "3.1.0", + "dev": true + }, + "define-property": { + "version": "0.2.5", "dev": true, "requires": { - "detect-indent": "^6.0.0", - "graceful-fs": "^4.1.15", - "is-plain-obj": "^2.0.0", - "make-dir": "^3.0.0", - "sort-keys": "^4.0.0", - "write-file-atomic": "^3.0.0" + "is-descriptor": "^0.1.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "@lerna/write-log-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-4.0.0.tgz", - "integrity": "sha512-XRG5BloiArpXRakcnPHmEHJp+4AtnhRtpDIHSghmXD5EichI1uD73J7FgPp30mm2pDRq3FdqB0NbwSEsJ9xFQg==", + "clean-stack": { + "version": "2.2.0" + }, + "cli-cursor": { + "version": "3.1.0", "dev": true, "requires": { - "npmlog": "^4.1.2", - "write-file-atomic": "^3.0.3" + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cli-width": { + "version": "3.0.0", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" }, "dependencies": { - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "ansi-regex": { + "version": "3.0.0", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true + }, + "string-width": { + "version": "2.1.1", "dev": true, "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" } } } }, - "@microsoft/api-extractor": { - "version": "7.9.11", + "clone": { + "version": "1.0.4", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", "dev": true, "requires": { - "@microsoft/api-extractor-model": "7.8.19", - "@microsoft/tsdoc": "0.12.19", - "@rushstack/node-core-library": "3.30.0", - "@rushstack/ts-command-line": "4.6.4", - "colors": "~1.2.1", - "lodash": "~4.17.15", - "resolve": "~1.17.0", - "semver": "~7.3.0", - "source-map": "~0.6.1", - "typescript": "~3.9.5" + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" }, "dependencies": { - "resolve": { - "version": "1.17.0", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "semver": { - "version": "7.3.2", + "kind-of": { + "version": "6.0.3", "dev": true } } }, - "@microsoft/api-extractor-model": { - "version": "7.8.19", + "clone-response": { + "version": "1.0.2", "dev": true, "requires": { - "@microsoft/tsdoc": "0.12.19", - "@rushstack/node-core-library": "3.30.0" + "mimic-response": "^1.0.0" } }, - "@microsoft/tsdoc": { - "version": "0.12.19", + "cmd-shim": { + "version": "4.1.0", + "dev": true, + "requires": { + "mkdirp-infer-owner": "^2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", + "code-point-at": { + "version": "1.1.0" + }, + "code-prettify": { + "version": "0.1.0", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", "dev": true, "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, - "@nodelib/fs.scandir": { - "version": "2.1.3", + "color-convert": { + "version": "1.9.1", "dev": true, "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" - }, - "dependencies": { - "@nodelib/fs.stat": { - "version": "2.0.3", - "dev": true - } + "color-name": "^1.1.1" } }, - "@nodelib/fs.stat": { - "version": "1.1.3", + "color-name": { + "version": "1.1.4", "dev": true }, - "@nodelib/fs.walk": { - "version": "1.2.4", + "color-support": { + "version": "1.1.3" + }, + "color-themes-for-google-code-prettify": { + "version": "2.0.4", + "dev": true + }, + "colors": { + "version": "1.2.5", + "dev": true + }, + "columnify": { + "version": "1.5.4", "dev": true, "requires": { - "@nodelib/fs.scandir": "2.1.3", - "fastq": "^1.6.0" + "strip-ansi": "^3.0.0", + "wcwidth": "^1.0.0" } }, - "@npmcli/ci-detect": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz", - "integrity": "sha512-3BGrt6FLjqM6br5AhWRKTr3u5GIVkjRYeAFrMp3HjnfICrg4xOrVRwFavKT6tsp++bq5dluL5t8ME/Nha/6c1Q==", + "combined-stream": { + "version": "1.0.8", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "dev": true, + "optional": true + }, + "comment-parser": { + "version": "1.3.1", "dev": true }, - "@npmcli/fs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz", - "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==", + "common-path-prefix": { + "version": "3.0.0", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "dev": true + }, + "compare-func": { + "version": "2.0.0", "dev": true, "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dot-prop": { + "version": "5.3.0", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "is-obj": "^2.0.0" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "is-obj": { + "version": "2.0.0", "dev": true } } }, - "@npmcli/git": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", - "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "component-emitter": { + "version": "1.2.1", + "dev": true + }, + "concat-map": { + "version": "0.0.1" + }, + "concat-stream": { + "version": "1.6.0", "dev": true, "requires": { - "@npmcli/promise-spawn": "^1.3.2", - "lru-cache": "^6.0.0", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^6.1.1", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "isarray": { + "version": "1.0.0", "dev": true }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "readable-stream": { + "version": "2.3.5", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "string_decoder": { + "version": "1.0.3", "dev": true, "requires": { - "isexe": "^2.0.0" + "safe-buffer": "~5.1.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "@npmcli/installed-package-contents": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", - "dev": true, - "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "config-chain": { + "version": "1.1.12", "dev": true, "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "@npmcli/node-gyp": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", - "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==", - "dev": true + "console-control-strings": { + "version": "1.1.0" }, - "@npmcli/promise-spawn": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", - "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "conventional-changelog-angular": { + "version": "5.0.13", "dev": true, "requires": { - "infer-owner": "^1.0.4" + "compare-func": "^2.0.0", + "q": "^1.5.1" } }, - "@npmcli/run-script": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.6.tgz", - "integrity": "sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g==", + "conventional-changelog-core": { + "version": "4.2.4", "dev": true, "requires": { - "@npmcli/node-gyp": "^1.0.2", - "@npmcli/promise-spawn": "^1.3.2", - "node-gyp": "^7.1.0", - "read-package-json-fast": "^2.0.1" + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" }, "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "hosted-git-info": { + "version": "4.0.2", "dev": true, "requires": { - "yallist": "^4.0.0" + "lru-cache": "^6.0.0" } }, - "node-gyp": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", - "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.3", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "request": "^2.88.2", - "rimraf": "^3.0.2", - "semver": "^7.3.2", - "tar": "^6.0.2", - "which": "^2.0.2" + "yallist": "^4.0.0" } }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "normalize-package-data": { + "version": "3.0.3", "dev": true, "requires": { - "abbrev": "1" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "readable-stream": { + "version": "3.6.0", "dev": true, "requires": { - "glob": "^7.1.3" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, + "safe-buffer": { + "version": "5.2.1", + "dev": true + }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "string_decoder": { + "version": "1.3.0", "dev": true, "requires": { - "isexe": "^2.0.0" + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "4.0.2", + "dev": true, + "requires": { + "readable-stream": "3" } }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", - "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", - "dev": true, - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.0", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true } } }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true - }, - "@octokit/plugin-enterprise-rest": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", + "conventional-changelog-preset-loader": { + "version": "2.3.4", "dev": true }, - "@octokit/plugin-paginate-rest": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", - "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", - "dev": true, - "requires": { - "@octokit/types": "^6.34.0" - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", - "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", - "dev": true, - "requires": { - "@octokit/types": "^6.34.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz", - "integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==", + "conventional-changelog-writer": { + "version": "5.0.0", "dev": true, "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.1", - "universal-user-agent": "^6.0.0" + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" }, "dependencies": { - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", "dev": true + }, + "semver": { + "version": "6.3.0", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "4.0.2", + "dev": true, + "requires": { + "readable-stream": "3" + } } } }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "18.12.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", - "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", - "dev": true, - "requires": { - "@octokit/core": "^3.5.1", - "@octokit/plugin-paginate-rest": "^2.16.8", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^5.12.0" - } - }, - "@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "conventional-commits-filter": { + "version": "2.0.7", "dev": true, "requires": { - "@octokit/openapi-types": "^11.2.0" + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" } }, - "@pixi-build-tools/api-extractor-lerna-monorepo": { - "version": "1.0.3", + "conventional-commits-parser": { + "version": "3.2.3", "dev": true, "requires": { - "@lerna/project": "~3.21.0" + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" }, "dependencies": { - "@lerna/package": { - "version": "3.16.0", + "readable-stream": { + "version": "3.6.0", "dev": true, "requires": { - "load-json-file": "^5.3.0", - "npm-package-arg": "^6.1.0", - "write-pkg": "^3.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "@lerna/project": { - "version": "3.21.0", + "safe-buffer": { + "version": "5.2.1", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", "dev": true, "requires": { - "@lerna/package": "3.16.0", - "@lerna/validation-error": "3.13.0", - "cosmiconfig": "^5.1.0", - "dedent": "^0.7.0", - "dot-prop": "^4.2.0", - "glob-parent": "^5.0.0", - "globby": "^9.2.0", - "load-json-file": "^5.3.0", - "npmlog": "^4.1.2", - "p-map": "^2.1.0", - "resolve-from": "^4.0.0", - "write-json-file": "^3.2.0" + "safe-buffer": "~5.2.0" } }, - "dir-glob": { - "version": "2.2.2", + "through2": { + "version": "4.0.2", "dev": true, "requires": { - "path-type": "^3.0.0" + "readable-stream": "3" } - }, - "glob-parent": { - "version": "5.1.2", + } + } + }, + "conventional-recommended-bump": { + "version": "6.1.0", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + }, + "dependencies": { + "concat-stream": { + "version": "2.0.0", "dev": true, "requires": { - "is-glob": "^4.0.1" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" } }, - "globby": { - "version": "9.2.0", + "readable-stream": { + "version": "3.6.0", "dev": true, "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "ignore": { - "version": "4.0.6", + "safe-buffer": { + "version": "5.2.1", "dev": true }, - "is-glob": { - "version": "4.0.1", + "string_decoder": { + "version": "1.3.0", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "safe-buffer": "~5.2.0" } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "dev": true + }, + "copyfiles": { + "version": "2.1.0", + "dev": true, + "requires": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^0.5.1", + "noms": "0.0.0", + "through2": "^2.0.1", + "yargs": "^11.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "dev": true }, - "load-json-file": { - "version": "5.3.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - } + "camelcase": { + "version": "4.1.0", + "dev": true }, - "make-dir": { + "find-up": { "version": "2.1.0", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "locate-path": "^2.0.0" } }, - "p-map": { - "version": "2.1.0", - "dev": true - }, - "pify": { - "version": "4.0.1", + "is-fullwidth-code-point": { + "version": "2.0.0", "dev": true }, - "semver": { - "version": "5.7.1", - "dev": true + "string-width": { + "version": "2.1.1", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } }, - "slash": { - "version": "2.0.0", - "dev": true + "strip-ansi": { + "version": "4.0.0", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } }, - "type-fest": { - "version": "0.3.1", - "dev": true + "yargs": { + "version": "11.1.0", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } }, - "write-json-file": { - "version": "3.2.0", + "yargs-parser": { + "version": "9.0.2", "dev": true, "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" + "camelcase": "^4.1.0" } } } }, - "@pixi/accessibility": { - "version": "file:packages/accessibility", - "requires": {} - }, - "@pixi/app": { - "version": "file:packages/app", - "requires": {} - }, - "@pixi/basis": { - "version": "file:packages/basis", - "requires": {} - }, - "@pixi/canvas-display": { - "version": "file:packages/canvas/canvas-display", - "requires": {} - }, - "@pixi/canvas-extract": { - "version": "file:packages/canvas/canvas-extract", - "requires": {} - }, - "@pixi/canvas-graphics": { - "version": "file:packages/canvas/canvas-graphics", - "requires": {} - }, - "@pixi/canvas-mesh": { - "version": "file:packages/canvas/canvas-mesh", - "requires": {} - }, - "@pixi/canvas-particle-container": { - "version": "file:packages/canvas/canvas-particle-container", - "requires": {} - }, - "@pixi/canvas-prepare": { - "version": "file:packages/canvas/canvas-prepare", - "requires": {} - }, - "@pixi/canvas-renderer": { - "version": "file:packages/canvas/canvas-renderer", - "requires": {} - }, - "@pixi/canvas-sprite": { - "version": "file:packages/canvas/canvas-sprite", - "requires": {} - }, - "@pixi/canvas-sprite-tiling": { - "version": "file:packages/canvas/canvas-sprite-tiling", - "requires": {} - }, - "@pixi/canvas-text": { - "version": "file:packages/canvas/canvas-text", - "requires": {} + "core-js": { + "version": "3.8.0", + "dev": true }, - "@pixi/compressed-textures": { - "version": "file:packages/compressed-textures", - "requires": {} + "core-util-is": { + "version": "1.0.2" }, - "@pixi/constants": { - "version": "file:packages/constants" + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true }, - "@pixi/core": { - "version": "file:packages/core", + "cross-env": { + "version": "5.2.0", + "dev": true, "requires": { - "@types/offscreencanvas": "^2019.6.4" + "cross-spawn": "^6.0.5", + "is-windows": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } } }, - "@pixi/display": { - "version": "file:packages/display", - "requires": {} + "cross-fetch": { + "version": "3.1.5", + "requires": { + "node-fetch": "2.6.7" + } }, - "@pixi/eslint-config": { - "version": "2.0.1", + "cross-spawn": { + "version": "5.1.0", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "^4.0.0", - "@typescript-eslint/parser": "^4.0.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, - "@pixi/events": { - "version": "file:packages/events", - "requires": {} - }, - "@pixi/extract": { - "version": "file:packages/extract", - "requires": {} - }, - "@pixi/filter-alpha": { - "version": "file:packages/filters/filter-alpha", - "requires": {} + "css-color-names": { + "version": "1.0.1", + "dev": true }, - "@pixi/filter-blur": { - "version": "file:packages/filters/filter-blur", - "requires": {} + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true }, - "@pixi/filter-color-matrix": { - "version": "file:packages/filters/filter-color-matrix", - "requires": {} + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } }, - "@pixi/filter-displacement": { - "version": "file:packages/filters/filter-displacement", - "requires": {} + "dargs": { + "version": "7.0.0", + "dev": true }, - "@pixi/filter-fxaa": { - "version": "file:packages/filters/filter-fxaa", - "requires": {} + "dashdash": { + "version": "1.14.1", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } }, - "@pixi/filter-noise": { - "version": "file:packages/filters/filter-noise", - "requires": {} + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } }, - "@pixi/graphics": { - "version": "file:packages/graphics", - "requires": {} + "dateformat": { + "version": "3.0.3", + "dev": true }, - "@pixi/graphics-extras": { - "version": "file:packages/graphics-extras", - "requires": {} + "debug": { + "version": "2.6.9", + "dev": true, + "requires": { + "ms": "2.0.0" + } }, - "@pixi/interaction": { - "version": "file:packages/interaction", - "requires": {} + "debuglog": { + "version": "1.0.1", + "dev": true }, - "@pixi/loaders": { - "version": "file:packages/loaders", - "requires": {} + "decamelize": { + "version": "1.2.0", + "dev": true }, - "@pixi/math": { - "version": "file:packages/math" + "decamelize-keys": { + "version": "1.1.0", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + } }, - "@pixi/math-extras": { - "version": "file:packages/math-extras", - "requires": {} + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true }, - "@pixi/mesh": { - "version": "file:packages/mesh", - "requires": {} + "decode-uri-component": { + "version": "0.2.0", + "dev": true }, - "@pixi/mesh-extras": { - "version": "file:packages/mesh-extras", - "requires": {} + "decompress-response": { + "version": "3.3.0", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } }, - "@pixi/mixin-cache-as-bitmap": { - "version": "file:packages/mixin-cache-as-bitmap", - "requires": {} + "dedent": { + "version": "0.7.0", + "dev": true }, - "@pixi/mixin-get-child-by-name": { - "version": "file:packages/mixin-get-child-by-name", - "requires": {} + "deep-extend": { + "version": "0.6.0" }, - "@pixi/mixin-get-global-position": { - "version": "file:packages/mixin-get-global-position", - "requires": {} + "deep-is": { + "version": "0.1.3", + "dev": true }, - "@pixi/particle-container": { - "version": "file:packages/particle-container", - "requires": {} + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true }, - "@pixi/polyfill": { - "version": "file:packages/polyfill", + "defaults": { + "version": "1.0.3", + "dev": true, "requires": { - "@types/object-assign": "^4.0.30", - "@types/promise-polyfill": "^6.0.3", - "object-assign": "^4.1.1", - "promise-polyfill": "^8.2.0" + "clone": "^1.0.2" } }, - "@pixi/prepare": { - "version": "file:packages/prepare", - "requires": {} + "defer-to-connect": { + "version": "1.1.3", + "dev": true }, - "@pixi/runner": { - "version": "file:packages/runner" + "define-properties": { + "version": "1.1.3", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } }, - "@pixi/settings": { - "version": "file:packages/settings", + "define-property": { + "version": "2.0.2", + "dev": true, "requires": { - "ismobilejs": "^1.1.0" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "dev": true + } } }, - "@pixi/sprite": { - "version": "file:packages/sprite", - "requires": {} + "delayed-stream": { + "version": "1.0.0", + "dev": true }, - "@pixi/sprite-animated": { - "version": "file:packages/sprite-animated", - "requires": {} + "delegates": { + "version": "1.0.0" }, - "@pixi/sprite-tiling": { - "version": "file:packages/sprite-tiling", - "requires": {} + "depd": { + "version": "1.1.2" }, - "@pixi/spritesheet": { - "version": "file:packages/spritesheet", - "requires": {} + "deprecation": { + "version": "2.3.1", + "dev": true }, - "@pixi/text": { - "version": "file:packages/text", - "requires": {} + "detect-indent": { + "version": "5.0.0", + "dev": true }, - "@pixi/text-bitmap": { - "version": "file:packages/text-bitmap", - "requires": {} + "detect-libc": { + "version": "2.0.1" }, - "@pixi/ticker": { - "version": "file:packages/ticker", - "requires": {} + "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 }, - "@pixi/unsafe-eval": { - "version": "file:packages/unsafe-eval", - "requires": {} + "detect-node": { + "version": "2.0.5", + "dev": true, + "optional": true }, - "@pixi/utils": { - "version": "file:packages/utils", + "dezalgo": { + "version": "1.0.3", + "dev": true, "requires": { - "@types/earcut": "^2.1.0", - "css-color-names": "^1.0.1", - "earcut": "^2.2.2", - "eventemitter3": "^3.1.0", - "url": "^0.11.0" + "asap": "^2.0.0", + "wrappy": "1" } }, - "@pixi/webdoc-template": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@pixi/webdoc-template/-/webdoc-template-1.5.3.tgz", - "integrity": "sha512-Q988OAvg0NsfoSE6Bl99Lej1l4O1QgV09ZWAnDDKi7FDSGxhY+sQpenN4DEmB27rzW5RJiST3irnTKq1S5TnKg==", + "diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", "dev": true, "requires": { - "code-prettify": "^0.1.0", - "color-themes-for-google-code-prettify": "^2.0.4", - "common-path-prefix": "^3.0.0", - "fs-extra": "^9.0.1", - "klaw-sync": "^6.0.0", - "lodash": "*", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.4.0", - "missionlog": "^1.6.0", - "open-sans-fonts": "^1.6.2", - "taffydb": "^2.7.3" + "path-type": "^4.0.0" }, "dependencies": { - "fs-extra": { - "version": "9.1.0", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", + "path-type": { + "version": "4.0.0", "dev": true } } }, - "@rollup/plugin-alias": { - "version": "3.1.1", + "doctrine": { + "version": "3.0.0", "dev": true, "requires": { - "slash": "^3.0.0" + "esutils": "^2.0.2" } }, - "@rollup/plugin-buble": { - "version": "0.21.3", + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.0.8", - "@types/buble": "^0.19.2", - "buble": "^0.20.0" + "webidl-conversions": "^5.0.0" }, "dependencies": { - "buble": { - "version": "0.20.0", - "dev": true, - "requires": { - "acorn": "^6.4.1", - "acorn-dynamic-import": "^4.0.0", - "acorn-jsx": "^5.2.0", - "chalk": "^2.4.2", - "magic-string": "^0.25.7", - "minimist": "^1.2.5", - "regexpu-core": "4.5.4" - } - }, - "magic-string": { - "version": "0.25.7", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regexpu-core": { - "version": "4.5.4", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", "dev": true } } }, - "@rollup/plugin-commonjs": { - "version": "15.1.0", + "duplexer": { + "version": "0.1.2", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" + "readable-stream": "~1.1.9" }, "dependencies": { - "estree-walker": { - "version": "2.0.1", - "dev": true - }, - "magic-string": { - "version": "0.25.7", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "resolve": { - "version": "1.18.1", + "readable-stream": { + "version": "1.1.14", "dev": true, "requires": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } } } }, - "@rollup/plugin-json": { - "version": "4.1.0", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.0.8" - } + "duplexer3": { + "version": "0.1.4", + "dev": true }, - "@rollup/plugin-node-resolve": { - "version": "9.0.0", + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.17.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" }, "dependencies": { - "@types/resolve": { - "version": "1.17.1", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "@types/node": "*" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "deepmerge": { - "version": "4.2.2", - "dev": true - }, - "resolve": { - "version": "1.18.1", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" + "safe-buffer": "~5.1.0" } } } }, - "@rollup/plugin-typescript": { - "version": "6.0.0", + "earcut": { + "version": "2.2.4" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", - "resolve": "^1.17.0" - }, - "dependencies": { - "resolve": { - "version": "1.18.1", - "dev": true, - "requires": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - } - } + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "@rollup/pluginutils": { - "version": "3.1.0", + "electron": { + "version": "12.0.2", "dev": true, "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" + "@electron/get": "^1.0.1", + "@types/node": "^14.6.2", + "extract-zip": "^1.0.3" }, "dependencies": { - "@types/estree": { - "version": "0.0.39", - "dev": true - }, - "estree-walker": { - "version": "1.0.1", + "@types/node": { + "version": "14.14.35", "dev": true } } }, - "@rushstack/node-core-library": { - "version": "3.30.0", + "electron-to-chromium": { + "version": "1.4.199", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.199.tgz", + "integrity": "sha512-WIGME0Cs7oob3mxsJwHbeWkH0tYkIE/sjkJ8ML2BYmuRcjhRl/q5kVDXG7W9LOOKwzPU5M0LBlXRq9rlSgnNlg==", + "dev": true + }, + "emittery": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", + "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", "dev": true, + "optional": true + }, + "encoding": { + "version": "0.1.13", + "optional": true, "requires": { - "@types/node": "10.17.13", - "colors": "~1.2.1", - "fs-extra": "~7.0.1", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.17.0", - "semver": "~7.3.0", - "timsort": "~0.3.0", - "z-schema": "~3.18.3" + "iconv-lite": "^0.6.2" }, "dependencies": { - "@types/node": { - "version": "10.17.13", - "dev": true - }, - "fs-extra": { - "version": "7.0.1", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "resolve": { - "version": "1.17.0", - "dev": true, + "iconv-lite": { + "version": "0.6.3", + "optional": true, "requires": { - "path-parse": "^1.0.6" + "safer-buffer": ">= 2.1.2 < 3.0.0" } - }, - "semver": { - "version": "7.3.2", - "dev": true } } }, - "@rushstack/ts-command-line": { - "version": "4.6.4", - "dev": true, + "end-of-stream": { + "version": "1.4.1", "requires": { - "@types/argparse": "1.0.38", - "argparse": "~1.0.9", - "colors": "~1.2.1", - "string-argv": "~0.3.1" + "once": "^1.4.0" } }, - "@sindresorhus/is": { - "version": "0.14.0", + "entities": { + "version": "2.0.3", "dev": true }, - "@sinonjs/commons": { - "version": "1.4.0", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } + "env-paths": { + "version": "2.2.1" }, - "@sinonjs/formatio": { - "version": "3.2.1", + "envinfo": { + "version": "7.8.1", + "dev": true + }, + "err-code": { + "version": "2.0.3" + }, + "error-ex": { + "version": "1.3.2", "dev": true, "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" + "is-arrayish": "^0.2.1" } }, - "@sinonjs/samsam": { - "version": "3.3.2", + "es-abstract": { + "version": "1.19.1", "dev": true, "requires": { - "@sinonjs/commons": "^1.0.2", - "array-from": "^2.1.1", - "lodash": "^4.17.11" + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" } }, - "@sinonjs/text-encoding": { - "version": "0.7.1", + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", "dev": true }, - "@szmarczak/http-timer": { - "version": "1.1.2", + "es-to-primitive": { + "version": "1.2.1", "dev": true, "requires": { - "defer-to-connect": "^1.0.1" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true + "es6-error": { + "version": "4.1.1", + "dev": true, + "optional": true }, - "@types/argparse": { - "version": "1.0.38", - "dev": true + "esbuild": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz", + "integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==", + "dev": true, + "requires": { + "esbuild-android-64": "0.14.49", + "esbuild-android-arm64": "0.14.49", + "esbuild-darwin-64": "0.14.49", + "esbuild-darwin-arm64": "0.14.49", + "esbuild-freebsd-64": "0.14.49", + "esbuild-freebsd-arm64": "0.14.49", + "esbuild-linux-32": "0.14.49", + "esbuild-linux-64": "0.14.49", + "esbuild-linux-arm": "0.14.49", + "esbuild-linux-arm64": "0.14.49", + "esbuild-linux-mips64le": "0.14.49", + "esbuild-linux-ppc64le": "0.14.49", + "esbuild-linux-riscv64": "0.14.49", + "esbuild-linux-s390x": "0.14.49", + "esbuild-netbsd-64": "0.14.49", + "esbuild-openbsd-64": "0.14.49", + "esbuild-sunos-64": "0.14.49", + "esbuild-windows-32": "0.14.49", + "esbuild-windows-64": "0.14.49", + "esbuild-windows-arm64": "0.14.49" + } + }, + "esbuild-android-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz", + "integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==", + "dev": true, + "optional": true }, - "@types/buble": { - "version": "0.19.2", + "esbuild-android-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz", + "integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==", "dev": true, - "requires": { - "magic-string": "^0.25.0" - } + "optional": true }, - "@types/color-name": { - "version": "1.1.1", - "dev": true + "esbuild-darwin-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz", + "integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==", + "dev": true, + "optional": true }, - "@types/earcut": { - "version": "2.1.1" + "esbuild-darwin-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz", + "integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==", + "dev": true, + "optional": true }, - "@types/estree": { - "version": "0.0.45", - "dev": true + "esbuild-freebsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz", + "integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==", + "dev": true, + "optional": true }, - "@types/glob": { - "version": "7.1.3", + "esbuild-freebsd-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz", + "integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==", "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } + "optional": true }, - "@types/json-schema": { - "version": "7.0.6", - "dev": true + "esbuild-linux-32": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz", + "integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==", + "dev": true, + "optional": true }, - "@types/minimatch": { - "version": "3.0.3", - "dev": true + "esbuild-linux-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz", + "integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==", + "dev": true, + "optional": true }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true + "esbuild-linux-arm": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz", + "integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==", + "dev": true, + "optional": true }, - "@types/mocha": { - "version": "8.2.3", - "dev": true + "esbuild-linux-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz", + "integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==", + "dev": true, + "optional": true }, - "@types/node": { - "version": "12.7.5", - "dev": true + "esbuild-linux-mips64le": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz", + "integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==", + "dev": true, + "optional": true }, - "@types/normalize-package-data": { - "version": "2.4.0", - "dev": true + "esbuild-linux-ppc64le": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz", + "integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==", + "dev": true, + "optional": true }, - "@types/object-assign": { - "version": "4.0.30", - "dev": true + "esbuild-linux-riscv64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz", + "integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==", + "dev": true, + "optional": true }, - "@types/offscreencanvas": { - "version": "2019.6.4", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz", - "integrity": "sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==" + "esbuild-linux-s390x": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz", + "integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==", + "dev": true, + "optional": true }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "esbuild-netbsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz", + "integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==", + "dev": true, + "optional": true }, - "@types/promise-polyfill": { - "version": "6.0.3", - "dev": true + "esbuild-openbsd-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz", + "integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==", + "dev": true, + "optional": true }, - "@typescript-eslint/eslint-plugin": { - "version": "4.12.0", + "esbuild-sunos-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz", + "integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==", "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.12.0", - "@typescript-eslint/scope-manager": "4.12.0", - "debug": "^4.1.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.0.0", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "lru-cache": { - "version": "6.0.0", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "ms": { - "version": "2.1.2", - "dev": true - }, - "semver": { - "version": "7.3.4", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "dev": true - } - } + "optional": true }, - "@typescript-eslint/experimental-utils": { - "version": "4.12.0", + "esbuild-windows-32": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz", + "integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==", "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.12.0", - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/typescript-estree": "4.12.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } + "optional": true }, - "@typescript-eslint/parser": { - "version": "4.12.0", + "esbuild-windows-64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz", + "integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==", "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.12.0", - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/typescript-estree": "4.12.0", - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "dev": true - } - } + "optional": true }, - "@typescript-eslint/scope-manager": { - "version": "4.12.0", + "esbuild-windows-arm64": { + "version": "0.14.49", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz", + "integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==", "dev": true, - "requires": { - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/visitor-keys": "4.12.0" - } + "optional": true }, - "@typescript-eslint/types": { - "version": "4.12.0", + "escalade": { + "version": "3.1.1", "dev": true }, - "@typescript-eslint/typescript-estree": { - "version": "4.12.0", + "escape-string-regexp": { + "version": "1.0.5", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.12.0", - "@typescript-eslint/visitor-keys": "4.12.0", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "dependencies": { - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - } + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true }, - "is-glob": { - "version": "4.0.1", + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, - "lru-cache": { - "version": "6.0.0", + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "yallist": "^4.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, - "ms": { - "version": "2.1.2", + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true }, - "semver": { - "version": "7.3.4", + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "prelude-ls": "~1.1.2" } - }, - "yallist": { - "version": "4.0.0", - "dev": true } } }, - "@typescript-eslint/visitor-keys": { - "version": "4.12.0", + "eslint": { + "version": "7.2.0", "dev": true, "requires": { - "@typescript-eslint/types": "4.12.0", - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.0.0", - "dev": true - } - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "dev": true - }, - "@webdoc/cli": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/cli/-/cli-1.5.5.tgz", - "integrity": "sha512-RbC3BzwGKHn1r+zoWRBqtGFb5tJEG9/IkZoDKUlgSO7h5MkSl2HKj9/vmW2giv8MdoiZnF7WRDWwSDkWcdDunA==", - "dev": true, - "requires": { - "@webdoc/default-template": "^1.5.5", - "@webdoc/externalize": "^1.5.5", - "@webdoc/legacy-template": "^1.5.5", - "@webdoc/model": "^1.5.5", - "@webdoc/parser": "^1.5.5", - "@webdoc/plugin-markdown": "^1.5.5", - "@webdoc/template-library": "^1.5.5", - "@webdoc/types": "^1.5.5", - "array.prototype.flatmap": "~1.2.3", - "fs-extra": "^9.0.1", - "globby": "11.0.0", - "lodash.merge": "4.6.2", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0", - "missionlog": "1.6.0", - "object.fromentries": "^2.0.2", - "perf_hooks": "~0.0.1", - "pkg-up": "~3.1.0", - "read-pkg-up": "~7.0.1", - "yargs": "^16.2.0" + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.0.0", + "eslint-visitor-keys": "^1.2.0", + "espree": "^7.1.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "@nodelib/fs.stat": { - "version": "2.0.4", - "dev": true - }, "ansi-regex": { "version": "5.0.0", "dev": true }, "ansi-styles": { - "version": "4.3.0", + "version": "4.2.1", "dev": true, "requires": { + "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, - "array-union": { - "version": "2.1.0", - "dev": true - }, - "braces": { - "version": "3.0.2", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "cliui": { - "version": "7.0.4", + "chalk": { + "version": "4.1.0", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "color-convert": { @@ -25137,41 +33434,24 @@ "color-name": "~1.1.4" } }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "fast-glob": { - "version": "3.2.5", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "fill-range": { - "version": "7.0.1", + "cross-spawn": { + "version": "7.0.3", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "fs-extra": { - "version": "9.1.0", + "debug": { + "version": "4.1.1", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "ms": "^2.1.1" } }, - "get-caller-file": { - "version": "2.0.5", + "eslint-visitor-keys": { + "version": "1.2.0", "dev": true }, "glob-parent": { @@ -25181,22 +33461,29 @@ "is-glob": "^4.0.1" } }, - "globby": { - "version": "11.0.0", + "globals": { + "version": "12.4.0", "dev": true, "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" + "type-fest": "^0.8.1" } }, - "is-fullwidth-code-point": { - "version": "3.0.0", + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "ignore": { + "version": "4.0.6", "dev": true }, + "import-fresh": { + "version": "3.2.1", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "is-glob": { "version": "4.0.1", "dev": true, @@ -25204,1079 +33491,1347 @@ "is-extglob": "^2.1.1" } }, - "is-number": { - "version": "7.0.0", + "ms": { + "version": "2.1.2", "dev": true }, - "jsonfile": { - "version": "6.1.0", + "path-key": { + "version": "3.1.1", + "dev": true + }, + "semver": { + "version": "7.3.2", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "shebang-regex": "^3.0.0" } }, - "micromatch": { - "version": "4.0.2", + "shebang-regex": { + "version": "3.0.0", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" + "ansi-regex": "^5.0.0" } }, - "parse-json": { - "version": "5.2.0", + "supports-color": { + "version": "7.1.0", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "has-flag": "^4.0.0" } }, - "read-pkg": { - "version": "5.2.0", + "which": { + "version": "2.0.2", "dev": true, "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "dev": true - } + "isexe": "^2.0.0" } - }, - "read-pkg-up": { - "version": "7.0.1", + } + } + }, + "eslint-plugin-jsdoc": { + "version": "39.2.9", + "dev": true, + "requires": { + "@es-joy/jsdoccomment": "~0.29.0", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.4.0", + "semver": "^7.3.7", + "spdx-expression-parse": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", "dev": true, "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" + "ms": "2.1.2" } }, - "string-width": { - "version": "4.2.0", + "escape-string-regexp": { + "version": "4.0.0", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "yallist": "^4.0.0" } }, - "strip-ansi": { - "version": "6.0.0", + "ms": { + "version": "2.1.2", + "dev": true + }, + "semver": { + "version": "7.3.7", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "lru-cache": "^6.0.0" } }, - "to-regex-range": { - "version": "5.0.1", + "yallist": { + "version": "4.0.0", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.0.0", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "dev": true + }, + "espree": { + "version": "7.1.0", + "dev": true, + "requires": { + "acorn": "^7.2.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.2.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.2.0", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "dev": true + }, + "estree-walker": { + "version": "0.6.0", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "dev": true + }, + "eventemitter3": { + "version": "3.1.2" + }, + "exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", "dev": true, "requires": { - "is-number": "^7.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "universalify": { - "version": "2.0.0", + "get-stream": { + "version": "6.0.1", "dev": true }, - "wrap-ansi": { - "version": "7.0.0", + "is-stream": { + "version": "2.0.1", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "path-key": "^3.0.0" } }, - "y18n": { - "version": "5.0.5", + "path-key": { + "version": "3.1.1", "dev": true }, - "yargs": { - "version": "16.2.0", + "shebang-command": { + "version": "2.0.0", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "shebang-regex": "^3.0.0" } }, - "yargs-parser": { - "version": "20.2.4", + "shebang-regex": { + "version": "3.0.0", "dev": true + }, + "which": { + "version": "2.0.2", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, - "@webdoc/default-template": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/default-template/-/default-template-1.5.5.tgz", - "integrity": "sha512-5XeHVYqUL2Mrm/bSImg3OAnAkeXMxANRPgRroHj6Aty7kkcSYOwN37Ns/oPsGKWeU5BJvxZO7Y0+Zzs7J9X/gw==", + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", "dev": true, "requires": { - "@babel/core": "^7.9.0", - "@babel/preset-react": "^7.10.1", - "@webdoc/model": "^1.5.5", - "@webdoc/template-library": "^1.5.5", - "@webdoc/types": "^1.5.5", - "code-prettify": "^0.1.0", - "fs-extra": "^9.0.1", - "highlight.js": "~10.7.2", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { - "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==", + "define-property": { + "version": "0.2.5", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "is-descriptor": "^0.1.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "extend-shallow": { + "version": "2.0.1", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "is-extendable": "^0.1.0" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, - "@webdoc/externalize": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/externalize/-/externalize-1.5.5.tgz", - "integrity": "sha512-cvDpVd4nX+n6vAwgabt5QXVXxPBKvat5CsydHwdErww/XTDRCZzy3sbCtzGBwyd4ZNrx3aSl4nJSAJjwf/WsUQ==", - "dev": true, - "requires": { - "@babel/core": "^7.9.0", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", - "lodash": "^4.17.20" - } + "expand-template": { + "version": "2.0.3" }, - "@webdoc/legacy-template": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/legacy-template/-/legacy-template-1.5.5.tgz", - "integrity": "sha512-Pvx1WwOMGjFNbd24T9LEqB8traj3DP75GUFweQ2vL2hyHg3hS7fpDsTttw7ePlm1usylhZFvJ37AgCID9a5WcA==", + "expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", "dev": true, "requires": { - "@webdoc/model": "^1.5.5", - "@webdoc/template-library": "^1.5.5", - "bluebird": "^3.7.2", - "code-prettify": "^0.1.0", - "color-themes-for-google-code-prettify": "^2.0.4", - "common-path-prefix": "^3.0.0", - "escape-string-regexp": "^3.0.0", - "fs-extra": "^9.0.1", - "klaw-sync": "6.0.0", - "lodash": "^4.17.20", - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0", - "marked": "^0.8.2", - "missionlog": "1.6.0", - "open-sans-fonts": "^1.6.2" + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" }, "dependencies": { - "escape-string-regexp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-3.0.0.tgz", - "integrity": "sha512-11dXIUC3umvzEViLP117d0KN6LJzZxh5+9F4E/7WLAAw7GrHk8NpUR+g9iJi/pe9C0py4F8rs0hreyRCwlAuZg==", - "dev": true + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } }, - "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==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "color-name": "~1.1.4" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "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 + }, + "jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "@webdoc/model": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/model/-/model-1.5.5.tgz", - "integrity": "sha512-fqFXe9VbtcooAkZGOD8hilux86FQKhnD2KQCXxbS/sip50WbZGegHWnJrYQIH9FwXbXuTENw7ztc8LsMY2pkMQ==", - "dev": true, - "requires": { - "@webdoc/types": "^1.5.5", - "catharsis": "0.8.11", - "nanoid": "~3.1.16", - "taffydb": "2.7.3" - } + "extend": { + "version": "3.0.2", + "dev": true }, - "@webdoc/parser": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/parser/-/parser-1.5.5.tgz", - "integrity": "sha512-Fpow4bMSSkBY52r57mnn3fuVREcc1rOoWdRxQcI/BjDfiAXz3xa7gH1xbXvxIE5LatN5dgRbYU81ILhCl18RvA==", + "extend-shallow": { + "version": "3.0.2", "dev": true, "requires": { - "@babel/parser": "^7.9.4", - "@babel/traverse": "7.9.5", - "@babel/types": "7.9.5", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", - "lodash": "^4.17.20", - "missionlog": "1.6.0", - "nanoid": "~3.1.16" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { - "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "is-extendable": { + "version": "1.0.1", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" + "is-plain-object": "^2.0.4" } } } }, - "@webdoc/plugin-markdown": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/plugin-markdown/-/plugin-markdown-1.5.5.tgz", - "integrity": "sha512-Mzu/stCH9eqOA4yyKE42k8EwIW3TQyj3euxc14Ohw/PVMC2Uk97u6JEiVQAuBSoi0vHp27rNVTICCtdLKxQFnQ==", + "external-editor": { + "version": "3.0.3", "dev": true, "requires": { - "markdown-it": "^11.0.0", - "markdown-it-highlightjs": "^3.1.0" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" } }, - "@webdoc/template-library": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/template-library/-/template-library-1.5.5.tgz", - "integrity": "sha512-nyNzLPj3g09bFdFNKEnNw0xxm1zy3+bdW17dhTREWKBgLQ7z7XrZeHTOI/jJ2zh4RFOIGExyYTx4nZ/luPhFEg==", + "extglob": { + "version": "2.0.4", "dev": true, "requires": { - "@webdoc/externalize": "^1.5.5", - "@webdoc/model": "^1.5.5", - "@webdoc/types": "^1.5.5", - "catharsis": "0.8.11", - "fs-extra": "^9.0.1", - "git-branch": "2.0.1", - "lodash": "^4.17.20", - "missionlog": "1.6.0", - "nanoid": "~3.1.16", - "node-fetch": "~2.6.1", - "parse-github-url": "1.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { - "fs-extra": { - "version": "9.1.0", + "define-property": { + "version": "1.0.0", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "kind-of": "^6.0.0" } }, - "jsonfile": { - "version": "6.1.0", + "is-descriptor": { + "version": "1.0.2", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, - "universalify": { - "version": "2.0.0", + "kind-of": { + "version": "6.0.2", "dev": true } } }, - "@webdoc/types": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@webdoc/types/-/types-1.5.5.tgz", - "integrity": "sha512-XTHsivrEgjSmZM4M6KbdNyJ859et6ifEgKy7TfLMAYbpgpZx7bOagSdKB33S7YICTaxxBFrlPeklGJKfFB6lNg==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.2.0", - "dev": true, - "requires": {} - }, - "add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "extract-zip": { + "version": "1.7.0", "dev": true, "requires": { - "debug": "4" + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "concat-stream": { + "version": "1.6.2", "dev": true, "requires": { - "ms": "2.1.2" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "isarray": { + "version": "1.0.0", "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } } } }, - "agentkeepalive": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", - "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "extsprintf": { + "version": "1.3.0", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "dev": true + }, + "fast-glob": { + "version": "2.2.6", "dev": true, "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "is-glob": { + "version": "4.0.0", "dev": true, "requires": { - "ms": "2.1.2" + "is-extglob": "^2.1.1" } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true } } }, - "aggregate-error": { - "version": "3.1.0", + "fast-json-stable-stringify": { + "version": "2.0.0", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "dev": true + }, + "fastq": { + "version": "1.9.0", "dev": true, "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "reusify": "^1.0.4" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "bser": "2.1.1" } }, - "ansi-colors": { - "version": "4.1.1", - "dev": true - }, - "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==", + "fd-slicer": { + "version": "1.1.0", "dev": true, "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } + "pend": "~1.2.0" } }, - "ansi-regex": { - "version": "2.1.1", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", + "figures": { + "version": "3.2.0", "dev": true, "requires": { - "color-convert": "^1.9.0" + "escape-string-regexp": "^1.0.5" } }, - "anymatch": { - "version": "3.1.1", + "file-entry-cache": { + "version": "5.0.1", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "flat-cache": "^2.0.1" } }, - "append-transform": { - "version": "2.0.0", + "file-uri-to-path": { + "version": "1.0.0" + }, + "fill-range": { + "version": "4.0.0", "dev": true, "requires": { - "default-require-extensions": "^3.0.0" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "aproba": { - "version": "1.2.0", + "filter-obj": { + "version": "1.1.0", "dev": true }, - "archy": { - "version": "1.0.0", + "find-git-root": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/find-git-root/-/find-git-root-1.0.4.tgz", + "integrity": "sha512-468fmirKKgcrqfZfPn0xIpwZUUsZQcYXfx0RC2/jX39GPz83TwutQNZZhDrI6HqjO8cRejxQVaUY8GQdXopFfA==", "dev": true }, - "are-we-there-yet": { - "version": "1.1.5", + "find-up": { + "version": "4.1.0", "dev": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "dev": true + "locate-path": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } }, - "readable-stream": { - "version": "2.3.6", + "p-limit": { + "version": "2.3.0", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "p-try": "^2.0.0" } }, - "string_decoder": { - "version": "1.1.1", + "p-locate": { + "version": "4.1.0", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "p-limit": "^2.2.0" } + }, + "p-try": { + "version": "2.2.0", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "dev": true } } }, - "arg": { - "version": "4.1.3", - "dev": true - }, - "argparse": { - "version": "1.0.10", + "flat-cache": { + "version": "2.0.1", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" } }, - "arr-diff": { - "version": "4.0.0", + "flatted": { + "version": "2.0.2", "dev": true }, - "arr-flatten": { - "version": "1.1.0", + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true }, - "array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } }, - "array-from": { - "version": "2.1.1", + "for-in": { + "version": "1.0.2", "dev": true }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "forever-agent": { + "version": "0.6.1", "dev": true }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "form-data": { + "version": "2.3.3", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" } }, - "array-union": { - "version": "1.0.2", + "fragment-cache": { + "version": "0.2.1", "dev": true, "requires": { - "array-uniq": "^1.0.1" + "map-cache": "^0.2.2" } }, - "array-uniq": { - "version": "1.0.3", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "dev": true + "fs-constants": { + "version": "1.0.0" }, - "array.prototype.flatmap": { - "version": "1.2.4", + "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, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "function-bind": "^1.1.1" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "dependencies": { + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } } }, - "arrify": { - "version": "1.0.1", - "dev": true + "fs-minipass": { + "version": "2.1.0", + "requires": { + "minipass": "^3.0.0" + } }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "fs.realpath": { + "version": "1.0.0" }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "fsevents": { + "version": "2.3.2", "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } + "optional": true }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "function-bind": { + "version": "1.1.1", "dev": true }, - "assertion-error": { - "version": "1.1.0", + "functional-red-black-tree": { + "version": "1.0.1", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "dev": true + "gauge": { + "version": "2.7.4", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, - "astral-regex": { - "version": "1.0.0", + "gensync": { + "version": "1.0.0-beta.2", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "get-caller-file": { + "version": "1.0.3", "dev": true }, - "at-least-node": { - "version": "1.0.0", - "dev": true + "get-intrinsic": { + "version": "1.1.1", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } }, - "atob": { - "version": "2.1.2", + "get-package-type": { + "version": "0.1.0", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "get-pkg-repo": { + "version": "4.2.1", + "dev": true, + "requires": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "emoji-regex": { + "version": "8.0.0", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "dev": true + }, + "hosted-git-info": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "dev": true + } + } + }, + "get-port": { + "version": "5.1.1", "dev": true }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "get-stream": { + "version": "3.0.0", "dev": true }, - "balanced-match": { + "get-symbol-description": { "version": "1.0.0", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", "dev": true }, - "base": { - "version": "0.11.2", + "get-workspaces": { + "version": "0.5.2", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "@changesets/types": "^0.4.0", + "fs-extra": "^7.0.1", + "globby": "^9.2.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", + "dir-glob": { + "version": "2.2.2", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "path-type": "^3.0.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", + "fs-extra": { + "version": "7.0.1", "dev": true, "requires": { - "kind-of": "^6.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "is-data-descriptor": { - "version": "1.0.0", + "globby": { + "version": "9.2.0", "dev": true, "requires": { - "kind-of": "^6.0.0" + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" } }, - "is-descriptor": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "ignore": { + "version": "4.0.6", + "dev": true }, - "kind-of": { - "version": "6.0.2", + "pify": { + "version": "4.0.1", + "dev": true + }, + "slash": { + "version": "2.0.0", "dev": true } } }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "getpass": { + "version": "0.1.7", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "assert-plus": "^1.0.0" } }, - "before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "dev": true - }, - "boolean": { - "version": "3.0.2", + "git-raw-commits": { + "version": "2.0.10", "dev": true, - "optional": true + "requires": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "4.0.2", + "dev": true, + "requires": { + "readable-stream": "3" + } + } + } }, - "brace-expansion": { - "version": "1.1.11", + "git-remote-origin-url": { + "version": "2.0.0", "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "dev": true + } } }, - "braces": { - "version": "2.3.2", + "git-semver-tags": { + "version": "4.1.1", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "meow": "^8.0.0", + "semver": "^6.0.0" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "semver": { + "version": "6.3.0", + "dev": true } } }, - "browser-stdout": { - "version": "1.3.1", - "dev": true - }, - "browserslist": { - "version": "4.16.6", + "git-up": { + "version": "4.0.5", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" + "is-ssh": "^1.3.0", + "parse-url": "^6.0.0" } }, - "buffer-crc32": { - "version": "0.2.13", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "dev": true + "git-url-parse": { + "version": "11.6.0", + "dev": true, + "requires": { + "git-up": "^4.0.0" + } }, - "builtin-modules": { - "version": "3.1.0", - "dev": true + "gitconfiglocal": { + "version": "1.0.0", + "dev": true, + "requires": { + "ini": "^1.3.2" + } }, - "builtins": { - "version": "1.0.3", - "dev": true + "github-from-package": { + "version": "0.0.0" }, - "byline": { + "gl": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", - "dev": true - }, - "byte-size": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz", - "integrity": "sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==", - "dev": true - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" + "bindings": "^1.5.0", + "bit-twiddle": "^1.0.2", + "glsl-tokenizer": "^2.0.2", + "nan": "^2.15.0", + "node-abi": "^3.5.0", + "node-gyp": "^8.4.1", + "prebuild-install": "^7.0.0" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1" + }, + "are-we-there-yet": { + "version": "3.0.0", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "debug": { + "version": "4.3.4", + "requires": { + "ms": "2.1.2" + } + }, + "emoji-regex": { + "version": "8.0.0" + }, + "gauge": { + "version": "4.0.4", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0" + }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "make-fetch-happen": { + "version": "9.1.0", + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, + "ms": { + "version": "2.1.2" + }, + "node-gyp": { + "version": "8.4.1", + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + } + }, + "nopt": { + "version": "5.0.0", + "requires": { + "abbrev": "1" + } + }, + "npmlog": { + "version": "6.0.2", + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } }, "rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cacheable-request": { - "version": "6.1.0", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "dev": true, + "safe-buffer": { + "version": "5.2.1" + }, + "semver": { + "version": "7.3.7", "requires": { - "pump": "^3.0.0" + "lru-cache": "^6.0.0" } }, - "lowercase-keys": { - "version": "2.0.0", - "dev": true + "socks-proxy-agent": { + "version": "6.2.1", + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } }, - "normalize-url": { - "version": "4.5.0", - "dev": true - } - } - }, - "caching-transform": { - "version": "4.0.0", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, + "string_decoder": { + "version": "1.3.0", "requires": { - "semver": "^6.0.0" + "safe-buffer": "~5.2.0" } }, - "semver": { - "version": "6.3.0", - "dev": true + "string-width": { + "version": "4.2.3", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } }, - "write-file-atomic": { - "version": "3.0.3", - "dev": true, + "strip-ansi": { + "version": "6.0.1", "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "ansi-regex": "^5.0.1" } + }, + "which": { + "version": "2.0.2", + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "yallist": { + "version": "4.0.0" } } }, - "call-bind": { - "version": "1.0.2", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "dev": true - }, - "caller-callsite": { - "version": "2.0.0", - "dev": true, + "glob": { + "version": "7.1.7", "requires": { - "callsites": "^2.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "caller-path": { - "version": "2.0.0", + "glob-parent": { + "version": "3.1.0", "dev": true, "requires": { - "caller-callsite": "^2.0.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" } }, - "callsites": { - "version": "2.0.0", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "glob-to-regexp": { + "version": "0.3.0", "dev": true }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "global-agent": { + "version": "2.1.12", "dev": true, + "optional": true, "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" + "boolean": "^3.0.1", + "core-js": "^3.6.5", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" }, "dependencies": { - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true + "lru-cache": { + "version": "6.0.0", + "dev": true, + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "dev": true, + "optional": true } } }, - "caniuse-lite": { - "version": "1.0.30001222", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "catharsis": { - "version": "0.8.11", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", + "global-tunnel-ng": { + "version": "2.7.1", "dev": true, + "optional": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" } }, - "chardet": { - "version": "0.7.0", + "globals": { + "version": "11.11.0", "dev": true }, - "check-error": { + "globalthis": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.3" + } }, - "chokidar": { - "version": "3.5.1", + "globby": { + "version": "11.0.4", "dev": true, "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" }, "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "dev": true + }, "braces": { "version": "3.0.2", "dev": true, @@ -26284,6 +34839,17 @@ "fill-range": "^7.0.1" } }, + "fast-glob": { + "version": "3.2.7", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "fill-range": { "version": "7.0.1", "dev": true, @@ -26299,7 +34865,7 @@ } }, "is-glob": { - "version": "4.0.1", + "version": "4.0.3", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -26309,6 +34875,14 @@ "version": "7.0.0", "dev": true }, + "micromatch": { + "version": "4.0.4", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, "to-regex-range": { "version": "5.0.1", "dev": true, @@ -26318,1203 +34892,942 @@ } } }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chunkd": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "dev": true, + "glsl-tokenizer": { + "version": "2.1.5", "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "through2": "^0.6.3" }, "dependencies": { - "arr-union": { - "version": "3.1.0", - "dev": true - }, - "define-property": { - "version": "0.2.5", - "dev": true, + "through2": { + "version": "0.6.5", "requires": { - "is-descriptor": "^0.1.0" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } }, - "clean-stack": { - "version": "2.2.0", - "dev": true - }, - "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, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "4.1.0", + "got": { + "version": "9.6.0", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", + "get-stream": { + "version": "4.1.0", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "pump": "^3.0.0" } } } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true + "graceful-fs": { + "version": "4.2.6" }, - "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==", + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==", "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - } - } + "optional": true }, - "clone-response": { - "version": "1.0.2", + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" } }, - "cmd-shim": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz", - "integrity": "sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==", + "handlebars": { + "version": "4.7.7", "dev": true, "requires": { - "mkdirp-infer-owner": "^2.0.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" } }, - "code-point-at": { - "version": "1.1.0", - "dev": true - }, - "code-prettify": { - "version": "0.1.0", + "har-schema": { + "version": "2.0.0", "dev": true }, - "collection-visit": { - "version": "1.0.0", + "har-validator": { + "version": "5.1.5", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "ajv": "^6.12.3", + "har-schema": "^2.0.0" } }, - "color-convert": { - "version": "1.9.1", + "hard-rejection": { + "version": "2.1.0", + "dev": true + }, + "has": { + "version": "1.0.3", "dev": true, "requires": { - "color-name": "^1.1.1" + "function-bind": "^1.1.1" } }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "color-themes-for-google-code-prettify": { - "version": "2.0.4", + "has-bigints": { + "version": "1.0.1", "dev": true }, - "colorette": { - "version": "1.2.2", + "has-flag": { + "version": "3.0.0", "dev": true }, - "colors": { - "version": "1.2.5", + "has-symbols": { + "version": "1.0.2", "dev": true }, - "columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "has-tostringtag": { + "version": "1.0.0", "dev": true, "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" + "has-symbols": "^1.0.2" } }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "has-unicode": { + "version": "2.0.1" + }, + "has-value": { + "version": "1.0.0", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "common-path-prefix": { - "version": "3.0.0", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "dev": true - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "has-values": { + "version": "1.0.0", "dev": true, "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "kind-of": { + "version": "4.0.0", "dev": true, "requires": { - "is-obj": "^2.0.0" + "is-buffer": "^1.1.5" } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true } } }, - "component-emitter": { - "version": "1.2.1", + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "concat-map": { - "version": "0.0.1", + "highlight.js": { + "version": "10.7.3", "dev": true }, - "concat-stream": { - "version": "1.6.0", + "hosted-git-info": { + "version": "2.7.1", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true - }, - "readable-stream": { - "version": "2.3.5", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.0.3", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, - "config-chain": { - "version": "1.1.12", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "console-control-strings": { - "version": "1.1.0", - "dev": true - }, - "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, + "http-proxy-agent": { + "version": "4.0.1", "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2" + } } }, - "conventional-changelog-core": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", - "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", "dev": true, "requires": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" }, "dependencies": { - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "color-convert": "^2.0.1" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "yallist": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "color-name": "~1.1.4" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "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 + }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "whatwg-encoding": "^2.0.0" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "has-flag": "^4.0.0" } }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", "dev": true, "requires": { - "readable-stream": "3" + "iconv-lite": "0.6.3" + } + } + } + }, + "http-signature": { + "version": "1.2.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "requires": { + "ms": "2.1.2" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "ms": { + "version": "2.1.2" } } }, - "conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "human-signals": { + "version": "2.1.0", + "dev": true + }, + "humanize-ms": { + "version": "1.2.1", + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1" + }, + "ignore": { + "version": "5.1.9", + "dev": true + }, + "ignore-walk": { + "version": "3.0.4", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "import-lazy": { + "version": "4.0.0", "dev": true }, - "conventional-changelog-writer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", - "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", + "import-local": { + "version": "3.0.3", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4" + }, + "indent-string": { + "version": "4.0.0" + }, + "infer-owner": { + "version": "1.0.4" + }, + "inflight": { + "version": "1.0.6", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4" + }, + "ini": { + "version": "1.3.5" + }, + "init-package-json": { + "version": "2.0.5", "dev": true, "requires": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", - "handlebars": "^4.7.6", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" + "npm-package-arg": "^8.1.5", + "promzard": "^0.3.0", + "read": "~1.0.1", + "read-package-json": "^4.1.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^3.0.0" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "hosted-git-info": { + "version": "4.0.2", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "lru-cache": "^6.0.0" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "lru-cache": { + "version": "6.0.0", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "yallist": "^4.0.0" } }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "normalize-package-data": { + "version": "3.0.3", "dev": true, "requires": { - "readable-stream": "3" + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" } - } - } - }, - "conventional-commits-filter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", - "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - } - }, - "conventional-commits-parser": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", - "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + }, + "npm-package-arg": { + "version": "8.1.5", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "read-package-json": { + "version": "4.1.1", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "glob": "^7.1.1", + "json-parse-even-better-errors": "^2.3.0", + "normalize-package-data": "^3.0.0", + "npm-normalize-package-bin": "^1.0.0" } }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "semver": { + "version": "7.3.5", "dev": true, "requires": { - "readable-stream": "3" + "lru-cache": "^6.0.0" } + }, + "yallist": { + "version": "4.0.0", + "dev": true } } }, - "conventional-recommended-bump": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", - "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "inquirer": { + "version": "7.3.3", "dev": true, "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" }, "dependencies": { - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "ansi-regex": { + "version": "5.0.1", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" + "color-convert": "^2.0.1" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "chalk": { + "version": "4.1.2", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "color-convert": { + "version": "2.0.1", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "color-name": "~1.1.4" } - } - } - }, - "convert-source-map": { - "version": "1.7.0", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "dev": true - }, - "copyfiles": { - "version": "2.1.0", - "dev": true, - "requires": { - "glob": "^7.0.5", - "minimatch": "^3.0.3", - "mkdirp": "^0.5.1", - "noms": "0.0.0", - "through2": "^2.0.1", - "yargs": "^11.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "dev": true }, - "camelcase": { - "version": "4.1.0", + "emoji-regex": { + "version": "8.0.0", "dev": true }, - "find-up": { - "version": "2.1.0", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } + "has-flag": { + "version": "4.0.0", + "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", + "version": "3.0.0", "dev": true }, "string-width": { - "version": "2.1.1", + "version": "4.2.3", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "yargs": { - "version": "11.1.0", + "version": "6.0.1", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "ansi-regex": "^5.0.1" } }, - "yargs-parser": { - "version": "9.0.2", + "supports-color": { + "version": "7.2.0", "dev": true, "requires": { - "camelcase": "^4.1.0" + "has-flag": "^4.0.0" } } } }, - "core-js": { - "version": "3.8.0", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "dev": true - }, - "cosmiconfig": { - "version": "5.1.0", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "lodash.get": "^4.4.2", - "parse-json": "^4.0.0" - } - }, - "cross-env": { - "version": "5.2.0", + "internal-slot": { + "version": "1.0.3", "dev": true, "requires": { - "cross-spawn": "^6.0.5", - "is-windows": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" } }, - "cross-spawn": { - "version": "5.1.0", + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "loose-envify": "^1.0.0" } }, - "css-color-names": { - "version": "1.0.1", + "invert-kv": { + "version": "1.0.0", "dev": true }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true + "ip": { + "version": "1.1.5" }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "is-accessor-descriptor": { + "version": "0.1.6", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "kind-of": "^3.0.2" } }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "is-arrayish": { + "version": "0.2.1", "dev": true }, - "debug": { - "version": "2.6.9", + "is-bigint": { + "version": "1.0.2", + "dev": true + }, + "is-boolean-object": { + "version": "1.1.1", "dev": true, "requires": { - "ms": "2.0.0" + "call-bind": "^1.0.2" } }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "is-buffer": { + "version": "1.1.6", "dev": true }, - "decamelize": { - "version": "1.2.0", + "is-callable": { + "version": "1.2.4", "dev": true }, - "decamelize-keys": { - "version": "1.1.0", + "is-ci": { + "version": "2.0.0", "dev": true, "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "ci-info": "^2.0.0" } }, - "decode-uri-component": { - "version": "0.2.0", - "dev": true - }, - "decompress-response": { - "version": "3.3.0", + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "has": "^1.0.3" } }, - "dedent": { - "version": "0.7.0", - "dev": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "is-data-descriptor": { + "version": "0.1.4", "dev": true, "requires": { - "type-detect": "^4.0.0" + "kind-of": "^3.0.2" } }, - "deep-is": { - "version": "0.1.3", + "is-date-object": { + "version": "1.0.1", "dev": true }, - "default-require-extensions": { - "version": "3.0.0", + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", "dev": true, "requires": { - "strip-bom": "^4.0.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { - "strip-bom": { - "version": "4.0.0", + "kind-of": { + "version": "5.1.0", "dev": true } } }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, - "requires": { - "clone": "^1.0.2" - } + "optional": true }, - "defer-to-connect": { - "version": "1.1.3", + "is-extendable": { + "version": "0.1.1", "dev": true }, - "define-properties": { - "version": "1.1.3", - "dev": true, + "is-extglob": { + "version": "2.1.1", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", "requires": { - "object-keys": "^1.0.12" + "number-is-nan": "^1.0.0" } }, - "define-property": { - "version": "2.0.2", + "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 + }, + "is-glob": { + "version": "3.1.0", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.2", - "dev": true - } + "is-extglob": "^2.1.0" } }, - "delayed-stream": { + "is-gzip": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", "dev": true }, - "delegates": { + "is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true + }, + "is-lambda": { + "version": "1.0.1" + }, + "is-module": { "version": "1.0.0", "dev": true }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "is-negative-zero": { + "version": "2.0.1", "dev": true }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "is-number": { + "version": "3.0.0", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-number-object": { + "version": "1.0.5", "dev": true }, - "detect-file": { - "version": "1.0.0", + "is-plain-obj": { + "version": "1.1.0", "dev": true }, - "detect-indent": { - "version": "5.0.0", + "is-plain-object": { + "version": "2.0.4", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, - "detect-node": { - "version": "2.0.5", + "is-reference": { + "version": "1.2.1", "dev": true, - "optional": true + "requires": { + "@types/estree": "*" + } }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "is-regex": { + "version": "1.1.4", "dev": true, "requires": { - "asap": "^2.0.0", - "wrappy": "1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "diff": { - "version": "3.5.0", + "is-shared-array-buffer": { + "version": "1.0.1", + "dev": true + }, + "is-ssh": { + "version": "1.3.3", + "dev": true, + "requires": { + "protocols": "^1.1.0" + } + }, + "is-stream": { + "version": "1.1.0", "dev": true }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "is-string": { + "version": "1.0.7", "dev": true, "requires": { - "path-type": "^4.0.0" - }, - "dependencies": { - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - } + "has-tostringtag": "^1.0.0" } }, - "doctrine": { - "version": "3.0.0", + "is-symbol": { + "version": "1.0.4", "dev": true, "requires": { - "esutils": "^2.0.2" + "has-symbols": "^1.0.2" } }, - "dot-prop": { - "version": "4.2.0", + "is-text-path": { + "version": "1.0.1", "dev": true, "requires": { - "is-obj": "^1.0.0" + "text-extensions": "^1.0.0" } }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "is-typedarray": { + "version": "1.0.0", "dev": true }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "is-unicode-supported": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.2.0.tgz", + "integrity": "sha512-wH+U77omcRzevfIG8dDhTS0V9zZyweakfD01FULl97+0EHiJTTZtJqxPSkIIo/SDPv/i07k/C9jAPY+jwLLeUQ==", + "dev": true + }, + "is-weakref": { + "version": "1.0.1", "dev": true, "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - } + "call-bind": "^1.0.0" } }, - "duplexer3": { - "version": "0.1.4", + "is-windows": { + "version": "1.0.2", "dev": true }, - "earcut": { - "version": "2.2.2" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, + "optional": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "is-docker": "^2.0.0" } }, - "electron": { - "version": "12.0.2", + "isarray": { + "version": "0.0.1" + }, + "isexe": { + "version": "2.0.0" + }, + "ismobilejs": { + "version": "1.1.1", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", "dev": true, "requires": { - "@electron/get": "^1.0.1", - "@types/node": "^14.6.2", - "extract-zip": "^1.0.3" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "dependencies": { - "@types/node": { - "version": "14.14.35", + "semver": { + "version": "6.3.0", "dev": true } } }, - "electron-to-chromium": { - "version": "1.3.727", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "dev": true, - "optional": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "istanbul-lib-report": { + "version": "3.0.0", "dev": true, - "optional": true, "requires": { - "iconv-lite": "^0.6.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", "dev": true, - "optional": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "has-flag": "^4.0.0" } } } }, - "end-of-stream": { - "version": "1.4.1", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "2.0.3", - "dev": true - }, - "env-paths": { - "version": "2.2.1", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", + "istanbul-lib-source-maps": { + "version": "4.0.0", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "dev": true + } } }, - "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "istanbul-reports": { + "version": "3.0.2", "dev": true, "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "es-to-primitive": { - "version": "1.2.1", + "jest": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", + "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "@jest/core": "^26.6.3", + "import-local": "^3.0.2", + "jest-cli": "^26.6.3" } }, - "es6-error": { - "version": "4.1.1", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "dev": true - }, - "eslint": { - "version": "7.2.0", + "jest-changed-files": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz", + "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "@jest/types": "^26.6.2", + "execa": "^4.0.0", + "throat": "^5.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, "cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -27522,68 +35835,63 @@ "which": "^2.0.1" } }, - "debug": { - "version": "4.1.1", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "eslint-visitor-keys": { - "version": "1.2.0", - "dev": true - }, - "glob-parent": { - "version": "5.1.1", + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" } }, - "globals": { - "version": "12.4.0", + "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, "requires": { - "type-fest": "^0.8.1" + "pump": "^3.0.0" } }, - "has-flag": { - "version": "4.0.0", + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "ignore": { - "version": "4.0.6", + "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 }, - "import-fresh": { - "version": "3.2.1", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "is-glob": { + "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, "requires": { - "is-extglob": "^2.1.1" + "path-key": "^3.0.0" } }, - "ms": { - "version": "2.1.2", - "dev": true - }, "path-key": { "version": "3.1.1", - "dev": true - }, - "semver": { - "version": "7.3.2", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" @@ -27591,24 +35899,14 @@ }, "shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "strip-ansi": { - "version": "6.0.0", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -27616,970 +35914,1214 @@ } } }, - "eslint-scope": { - "version": "5.1.0", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.0.0", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.1.0", - "dev": true - }, - "espree": { - "version": "7.1.0", + "jest-cli": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", + "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==", "dev": true, "requires": { - "acorn": "^7.2.0", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.2.0" + "@jest/core": "^26.6.3", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "is-ci": "^2.0.0", + "jest-config": "^26.6.3", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "prompts": "^2.0.1", + "yargs": "^15.4.1" }, "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } }, - "eslint-visitor-keys": { - "version": "1.2.0", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "dev": true - }, - "esquery": { - "version": "1.3.1", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.1.0", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "esrecurse": { - "version": "4.2.1", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.3.0", - "dev": true - }, - "estree-walker": { - "version": "0.6.0", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "dev": true - }, - "eventemitter3": { - "version": "3.1.2" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "jest-config": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", + "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", "dev": true, "requires": { - "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" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.6.3", + "@jest/types": "^26.6.2", + "babel-jest": "^26.6.3", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.6.2", + "jest-environment-node": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.6.3", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "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 - }, - "is-stream": { + "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } }, - "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==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "path-key": "^3.0.0" + "to-regex-range": "^5.0.1" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "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 }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "is-number": "^7.0.0" } } } }, - "expand-brackets": { - "version": "2.1.4", + "jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "dependencies": { - "define-property": { - "version": "0.2.5", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "color-convert": "^2.0.1" } }, - "extend-shallow": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, - "expand-tilde": { - "version": "2.0.2", + "jest-docblock": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", + "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "detect-newline": "^3.0.0" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", + "jest-each": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", + "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } }, - "external-editor": { - "version": "3.0.3", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", + "jest-electron": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/jest-electron/-/jest-electron-0.1.12.tgz", + "integrity": "sha512-10Hjr1kpyWz5cj9Xs/Xfb8yvF1LZPVmyEMHu/A/VhgvIV5yiP9uD8FHNc4HAfEnZHM+wvpR5YfveBTUAiNfwnA==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "electron": "^11.4.6", + "jest-haste-map": "~24.9.0", + "jest-message-util": "~24.9.0", + "jest-mock": "~24.9.0", + "jest-resolve": "~24.9.0", + "jest-runner": "~24.9.0", + "jest-runtime": "~24.9.0", + "jest-util": "~24.9.0", + "throat": "^5.0.0", + "tslib": "^1.10.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" } }, - "extend-shallow": { - "version": "2.0.1", + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" } }, - "is-accessor-descriptor": { - "version": "1.0.0", + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" } }, - "is-data-descriptor": { - "version": "1.0.0", + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" } }, - "is-descriptor": { - "version": "1.0.2", + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" } }, - "kind-of": { - "version": "6.0.2", + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true - } - } - }, - "extract-zip": { - "version": "1.7.0", - "dev": true, - "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.2", + }, + "@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "@types/yargs-parser": "*" } }, - "isarray": { - "version": "1.0.0", + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, - "readable-stream": { - "version": "2.3.7", + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + } } }, - "string_decoder": { - "version": "1.1.1", + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, + "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 + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "2.2.6", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "dependencies": { - "is-glob": { - "version": "4.0.0", + }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "dev": true - }, - "fastq": { - "version": "1.9.0", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "fill-range": { - "version": "4.0.0", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" } - } - } - }, - "filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", - "dev": true - }, - "find-cache-dir": { - "version": "3.3.1", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", "dev": true, "requires": { - "semver": "^6.0.0" + "@types/babel__traverse": "^7.0.6" } }, - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "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, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "dependencies": { - "locate-path": { + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, + "cliui": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, "requires": { - "p-try": "^2.0.0" + "cssom": "0.3.x" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==", "dev": true }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", "dev": true - } - } - }, - "findup-sync": { - "version": "2.0.0", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "flat": { - "version": "5.0.2", - "dev": true - }, - "flat-cache": { - "version": "2.0.1", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.2", - "dev": true - }, - "floss": { - "version": "5.0.0", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "commander": "^7.0.0", - "glob": "^7.1.6", - "mocha": "^8.0.0", - "resolve": "^1.19.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "electron": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-11.5.0.tgz", + "integrity": "sha512-WjNDd6lGpxyiNjE3LhnFCAk/D9GIj1rU3GSDealVShhkkkPR3Vh4q8ErXGDl1OAO/faomVa10KoFPUN/pLbNxg==", + "dev": true, + "requires": { + "@electron/get": "^1.0.1", + "@types/node": "^12.0.12", + "extract-zip": "^1.0.3" + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "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 + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "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 + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" } }, - "chalk": { - "version": "4.1.0", + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" } }, - "color-convert": { - "version": "2.0.1", + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } }, - "commander": { - "version": "7.2.0", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "dev": true + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } }, - "resolve": { - "version": "1.20.0", + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" } }, - "supports-color": { - "version": "7.2.0", + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" } - } - } - }, - "for-in": { - "version": "1.0.2", - "dev": true - }, - "foreground-child": { - "version": "2.0.0", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" } }, - "path-key": { - "version": "3.1.1", + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", "dev": true }, - "shebang-command": { - "version": "2.0.0", + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + }, + "dependencies": { + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==", + "dev": true + } } }, - "shebang-regex": { - "version": "3.0.0", - "dev": true + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } }, - "which": { - "version": "2.0.2", + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", "dev": true, "requires": { - "isexe": "^2.0.0" + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } - } - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fromentries": { - "version": "1.3.2", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-package-type": { - "version": "0.1.0", - "dev": true - }, - "get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "dev": true, - "requires": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", "dev": true, "requires": { - "color-convert": "^2.0.1" + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" } }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==", + "dev": true + } } }, - "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==", + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", "dev": true, "requires": { - "color-name": "~1.1.4" + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" } }, - "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==", + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", "dev": true }, - "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 + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + } }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" } }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "yallist": "^4.0.0" + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" } }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "requires": { - "ansi-regex": "^5.0.1" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, - "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==", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "p-try": "^2.0.0" } }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } - } - }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "get-value": { - "version": "2.0.6", - "dev": true - }, - "get-workspaces": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/get-workspaces/-/get-workspaces-0.5.2.tgz", - "integrity": "sha512-99x72taQ9OUHhCmBS0B2WI/zwOtBOBPoyVNGs9+B0ag2GGhCjl/EaU9VQ8Zorx64TyVj1Am7bO+0J1KwDqo7OA==", - "dev": true, - "requires": { - "@changesets/types": "^0.4.0", - "fs-extra": "^7.0.1", - "globby": "^9.2.0" - }, - "dependencies": { - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "path-type": "^3.0.0" + "p-limit": "^2.0.0" } }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" } }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "slash": { @@ -28587,792 +37129,616 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true - } - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-branch": { - "version": "2.0.1", - "dev": true, - "requires": { - "findup-sync": "^2.0.0" - } - }, - "git-raw-commits": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", - "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + }, + "stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "escape-string-regexp": "^2.0.0" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "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, "requires": { - "safe-buffer": "~5.2.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "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, "requires": { - "readable-stream": "3" + "ansi-regex": "^4.1.0" } - } - } - }, - "git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", - "dev": true, - "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "git-semver-tags": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", - "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", - "dev": true, - "requires": { - "meow": "^8.0.0", - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "git-up": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", - "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^6.0.0" - } - }, - "git-url-parse": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", - "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", - "dev": true, - "requires": { - "git-up": "^4.0.0" - } - }, - "gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", - "dev": true, - "requires": { - "ini": "^1.3.2" - } - }, - "glob": { - "version": "7.1.7", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "dev": true - }, - "global-agent": { - "version": "2.1.12", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "core-js": "^3.6.5", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, - "optional": true, "requires": { - "yallist": "^4.0.0" + "has-flag": "^3.0.0" } }, - "semver": { - "version": "7.3.5", + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, - "optional": true, "requires": { - "lru-cache": "^6.0.0" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, - "yallist": { - "version": "4.0.0", + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", "dev": true, - "optional": true - } - } - }, - "global-modules": { - "version": "1.0.0", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "global-tunnel-ng": { - "version": "2.7.1", - "dev": true, - "optional": true, - "requires": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - } - }, - "globals": { - "version": "11.11.0", - "dev": true - }, - "globalthis": { - "version": "1.0.2", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "dependencies": { - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "requires": { + "punycode": "^2.1.0" + } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "iconv-lite": "0.4.24" } }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", "dev": true, "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, - "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==", + "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, "requires": { - "to-regex-range": "^5.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "async-limiter": "~1.0.0" } }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "is-number": "^7.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "got": { - "version": "9.6.0", + "jest-environment-jsdom": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", + "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", "dev": true, "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2", + "jsdom": "^16.4.0" }, "dependencies": { - "get-stream": { - "version": "4.1.0", + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "requires": { - "pump": "^3.0.0" + "@jest/types": "^26.6.2", + "@types/node": "*" } } } }, - "graceful-fs": { - "version": "4.2.6", - "dev": true - }, - "growl": { - "version": "1.10.5", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", + "jest-environment-node": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", + "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "jest-mock": "^26.6.2", + "jest-util": "^26.6.2" }, "dependencies": { - "kind-of": { - "version": "4.0.0", + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "@jest/types": "^26.6.2", + "@types/node": "*" } } } }, - "hasha": { - "version": "5.2.2", + "jest-extended": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-1.2.1.tgz", + "integrity": "sha512-eKZR5iDpyTkcDesj16FpIPnjAWQNUB81ZFQW08EIddM6iqO7DjRIi39td9qol+1dpJS4Mqr9Qzp8ZMhanbSeug==", "dev": true, "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" + "expect": "^26.6.2", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.4" }, "dependencies": { - "is-stream": { - "version": "2.0.0", + "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 - } - } - }, - "he": { - "version": "1.2.0", - "dev": true - }, - "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "ms": "2.1.2" + "color-convert": "^2.0.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", "dev": true + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } + "jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", "dev": true, "requires": { - "agent-base": "6", - "debug": "4" + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" }, "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "ms": "2.1.2" + "fill-range": "^7.0.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, - "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 - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", - "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", - "dev": true - }, - "ignore-walk": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", - "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-fresh": { - "version": "2.0.0", + "jest-jasmine2": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", + "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", "dev": true, "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" }, "dependencies": { - "resolve-from": { - "version": "3.0.0", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "import-lazy": { - "version": "4.0.0", - "dev": true - }, - "import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", + "jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" } }, - "inherits": { - "version": "2.0.3", - "dev": true - }, - "ini": { - "version": "1.3.5", - "dev": true - }, - "init-package-json": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-2.0.5.tgz", - "integrity": "sha512-u1uGAtEFu3VA6HNl/yUWw57jmKEMx8SKOxHhxjGnOFUiIlFnohKDFg4ZrPpv9wWqk44nDxGJAtqjdQFm+9XXQA==", - "dev": true, - "requires": { - "npm-package-arg": "^8.1.5", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "^4.1.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0" + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" }, "dependencies": { - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "color-convert": "^2.0.1" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "yallist": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "color-name": "~1.1.4" } }, - "npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", "dev": true, "requires": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" } }, - "read-package-json": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-4.1.1.tgz", - "integrity": "sha512-P82sbZJ3ldDrWCOSKxJT0r/CXMWR0OR3KRh55SgKo3p91GSIEEC32v3lSHAvO/UcH3/IoL7uqhOFBduAnwdldw==", + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "requires": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", "dev": true, "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -29382,6 +37748,15 @@ "color-convert": "^2.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -29401,11 +37776,14 @@ "color-name": "~1.1.4" } }, - "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 + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } }, "has-flag": { "version": "4.0.0", @@ -29413,30 +37791,20 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "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 }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "ansi-regex": "^5.0.1" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "supports-color": { @@ -29447,402 +37815,647 @@ "requires": { "has-flag": "^4.0.0" } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "invert-kv": { - "version": "1.0.0", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "dev": true - }, - "is-bigint": { - "version": "1.0.2", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.1", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-buffer": { - "version": "1.1.6", - "dev": true - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-date-object": { - "version": "1.0.1", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "@jest/types": "^24.9.0" }, "dependencies": { - "kind-of": { - "version": "5.1.0", - "dev": true + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } } } }, - "is-directory": { - "version": "0.3.1", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "3.1.0", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", - "dev": true - }, - "is-module": { - "version": "1.0.0", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-number-object": { - "version": "1.0.5", - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-reference": { - "version": "1.2.1", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { + "jest-raw-loader": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "resolved": "https://registry.npmjs.org/jest-raw-loader/-/jest-raw-loader-1.0.1.tgz", + "integrity": "sha512-g9oaAjeC4/rIJk1Wd3RxVbOfMizowM7LSjEJqa4R9qDX0OjQNABXOhH+GaznUp+DjTGVPi2vPPbQXyX87DOnYg==", "dev": true }, - "is-ssh": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", - "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", - "dev": true, - "requires": { - "protocols": "^1.1.0" - } - }, - "is-stream": { - "version": "1.1.0", + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", "dev": true }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", + "jest-resolve": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", + "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "@jest/types": "^26.6.2", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.6.2", + "read-pkg-up": "^7.0.1", + "resolve": "^1.18.1", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "jest-resolve-dependencies": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz", + "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==", "dev": true, "requires": { - "text-extensions": "^1.0.0" + "@jest/types": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-snapshot": "^26.6.2" } }, - "is-typedarray": { - "version": "1.0.0", - "dev": true - }, - "is-weakref": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", - "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "jest-runner": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", + "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", "dev": true, "requires": { - "call-bind": "^1.0.0" - } - }, - "is-windows": { - "version": "1.0.2", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "dev": true - }, - "ismobilejs": { - "version": "1.1.1" - }, - "isobject": { - "version": "3.0.1", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.7.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.6.2", + "jest-leak-detector": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, - "istanbul-lib-coverage": { - "version": "3.0.0", - "dev": true + "jest-runtime": { + "version": "26.6.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", + "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", + "dev": true, + "requires": { + "@jest/console": "^26.6.2", + "@jest/environment": "^26.6.2", + "@jest/fake-timers": "^26.6.2", + "@jest/globals": "^26.6.2", + "@jest/source-map": "^26.6.2", + "@jest/test-result": "^26.6.2", + "@jest/transform": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^0.6.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.6.3", + "jest-haste-map": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-mock": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.6.2", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "jest-validate": "^26.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "jest-mock": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", + "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, - "istanbul-lib-hook": { - "version": "3.0.0", + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", "dev": true, "requires": { - "append-transform": "^2.0.0" + "@types/node": "*", + "graceful-fs": "^4.2.4" } }, - "istanbul-lib-instrument": { - "version": "4.0.3", + "jest-snapshot": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", + "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", "dev": true, "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/types": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.6.2", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "6.3.0", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "istanbul-lib-processinfo": { - "version": "2.0.2", + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", "dev": true, "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "color-convert": "^2.0.1" } }, - "make-dir": { - "version": "3.1.0", + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "semver": "^6.0.0" + "fill-range": "^7.0.1" } }, - "p-map": { - "version": "3.0.0", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "aggregate-error": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "path-key": { - "version": "3.1.1", - "dev": true + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } }, - "rimraf": { - "version": "3.0.2", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "glob": "^7.1.3" + "to-regex-range": "^5.0.1" } }, - "semver": { - "version": "6.3.0", + "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 }, - "shebang-command": { - "version": "2.0.0", + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "shebang-regex": "^3.0.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, - "shebang-regex": { - "version": "3.0.0", - "dev": true + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } }, - "which": { - "version": "2.0.2", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "is-number": "^7.0.0" } } } }, - "istanbul-lib-report": { - "version": "3.0.0", + "jest-validate": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", + "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "@jest/types": "^26.6.2", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.3.0", + "leven": "^3.1.0", + "pretty-format": "^26.6.2" }, "dependencies": { - "has-flag": { - "version": "4.0.0", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "make-dir": { - "version": "3.1.0", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "semver": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "semver": { - "version": "6.3.0", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 }, "supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -29850,40 +38463,68 @@ } } }, - "istanbul-lib-source-maps": { - "version": "4.0.0", + "jest-watcher": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", + "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^26.6.2", + "string-length": "^4.0.1" }, "dependencies": { - "debug": { - "version": "4.3.2", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "ms": "2.1.2" + "color-convert": "^2.0.1" } }, - "ms": { - "version": "2.1.2", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "istanbul-reports": { - "version": "3.0.2", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, "jest-worker": { "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "requires": { "@types/node": "*", @@ -29893,14 +38534,10 @@ "dependencies": { "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 }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -29912,6 +38549,12 @@ "version": "1.4.0", "dev": true }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "dev": true @@ -29926,8 +38569,6 @@ }, "jsbn": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, "jscc": { @@ -29941,10 +38582,93 @@ "skip-regex": "^1.0.2" } }, - "jsesc": { - "version": "0.5.0", + "jsdoc-type-pratt-parser": { + "version": "3.0.1", "dev": true }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + } + } + }, "json-buffer": { "version": "3.0.0", "dev": true @@ -29959,8 +38683,6 @@ }, "json-schema": { "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-schema-traverse": { @@ -29976,11 +38698,16 @@ "dev": true }, "json5": { - "version": "2.2.0", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "jsonc-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", + "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "dev": true }, "jsonfile": { "version": "4.0.0", @@ -29991,14 +38718,10 @@ }, "jsonparse": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "JSONStream": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -30007,8 +38730,6 @@ }, "jsprim": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { "assert-plus": "1.0.0", @@ -30017,10 +38738,6 @@ "verror": "1.10.0" } }, - "just-extend": { - "version": "4.0.2", - "dev": true - }, "keyv": { "version": "3.1.0", "dev": true, @@ -30042,6 +38759,12 @@ "graceful-fs": "^4.1.11" } }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "lcid": { "version": "1.0.0", "dev": true, @@ -30049,10 +38772,14 @@ "invert-kv": "^1.0.0" } }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, "lerna": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-4.0.0.tgz", - "integrity": "sha512-DD/i1znurfOmNJb0OBw66NmNqiM8kF6uIrzrJ0wGE3VNdzeOhz9ziWLYiRaZDGGwgbcjOo6eIfcx9O5Qynz+kg==", "dev": true, "requires": { "@lerna/add": "4.0.0", @@ -30075,6 +38802,12 @@ "npmlog": "^4.1.2" } }, + "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 + }, "levn": { "version": "0.4.1", "dev": true, @@ -30085,8 +38818,6 @@ }, "libnpmaccess": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-4.0.3.tgz", - "integrity": "sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -30097,14 +38828,10 @@ "dependencies": { "aproba": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, "debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -30112,8 +38839,6 @@ }, "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30121,8 +38846,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -30130,8 +38853,6 @@ }, "make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dev": true, "requires": { "agentkeepalive": "^4.1.3", @@ -30154,14 +38875,10 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -30171,8 +38888,6 @@ }, "npm-registry-fetch": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", "dev": true, "requires": { "make-fetch-happen": "^9.0.1", @@ -30185,8 +38900,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30194,8 +38907,6 @@ }, "socks-proxy-agent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", "dev": true, "requires": { "agent-base": "^6.0.2", @@ -30205,16 +38916,12 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "libnpmpublish": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-4.0.2.tgz", - "integrity": "sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw==", "dev": true, "requires": { "normalize-package-data": "^3.0.2", @@ -30226,8 +38933,6 @@ "dependencies": { "debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -30235,8 +38940,6 @@ }, "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30244,8 +38947,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -30253,8 +38954,6 @@ }, "make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dev": true, "requires": { "agentkeepalive": "^4.1.3", @@ -30277,14 +38976,10 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -30295,8 +38990,6 @@ }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -30306,8 +38999,6 @@ }, "npm-registry-fetch": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", "dev": true, "requires": { "make-fetch-happen": "^9.0.1", @@ -30320,8 +39011,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30329,8 +39018,6 @@ }, "socks-proxy-agent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", "dev": true, "requires": { "agent-base": "^6.0.2", @@ -30340,12 +39027,19 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "lines-and-columns": { "version": "1.1.6", "dev": true @@ -30367,6 +39061,15 @@ "strip-bom": "^3.0.0" } }, + "localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dev": true, + "requires": { + "lie": "3.1.1" + } + }, "locate-path": { "version": "2.0.0", "dev": true, @@ -30381,12 +39084,6 @@ }, "lodash._reinterpolate": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", "dev": true }, "lodash.flow": { @@ -30403,18 +39100,20 @@ }, "lodash.ismatch": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, "lodash.merge": { "version": "4.6.2", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "lodash.template": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", "dev": true, "requires": { "lodash._reinterpolate": "^3.0.0", @@ -30423,72 +39122,48 @@ }, "lodash.templatesettings": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { "lodash._reinterpolate": "^3.0.0" } }, "log-symbols": { - "version": "4.0.0", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "chalk": { - "version": "4.1.0", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "lolex": { - "version": "4.1.0", - "dev": true - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "get-func-name": "^2.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" } }, "lowercase-keys": { "version": "1.0.1", "dev": true }, + "lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "dev": true + }, "lru-cache": { "version": "4.1.1", "dev": true, @@ -30505,10 +39180,14 @@ } }, "make-dir": { - "version": "1.3.0", - "dev": true, + "version": "3.1.0", "requires": { - "pify": "^3.0.0" + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0" + } } }, "make-error": { @@ -30517,8 +39196,6 @@ }, "make-fetch-happen": { "version": "8.0.14", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", - "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", "dev": true, "requires": { "agentkeepalive": "^4.1.3", @@ -30540,8 +39217,6 @@ "dependencies": { "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -30549,12 +39224,19 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, "map-cache": { "version": "0.2.2", "dev": true @@ -30589,12 +39271,6 @@ "lodash.flow": "^3.5.0" } }, - "marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", - "dev": true - }, "matcher": { "version": "3.0.0", "dev": true, @@ -30627,8 +39303,6 @@ }, "meow": { "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -30646,8 +39320,6 @@ "dependencies": { "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30655,8 +39327,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -30664,8 +39334,6 @@ }, "normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -30676,8 +39344,6 @@ }, "parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -30688,8 +39354,6 @@ }, "read-pkg": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", @@ -30700,14 +39364,10 @@ "dependencies": { "hosted-git-info": { "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -30718,22 +39378,16 @@ }, "semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "type-fest": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true } } }, "read-pkg-up": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { "find-up": "^4.1.0", @@ -30743,16 +39397,12 @@ "dependencies": { "type-fest": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true } } }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -30760,34 +39410,24 @@ }, "type-fest": { "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "yargs-parser": { "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } }, "merge-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, "merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { @@ -30815,16 +39455,18 @@ } } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", "dev": true }, "mime-types": { "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", "dev": true, "requires": { "mime-db": "1.50.0" @@ -30840,25 +39482,21 @@ }, "min-indent": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, "minimatch": { "version": "3.0.4", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "dev": true + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "minimist-options": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -30868,43 +39506,29 @@ "dependencies": { "kind-of": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true } } }, "minipass": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", - "dev": true, "requires": { "yallist": "^4.0.0" }, "dependencies": { "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "4.0.0" } } }, "minipass-collect": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-fetch": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, "requires": { "encoding": "^0.1.12", "minipass": "^3.1.0", @@ -30914,17 +39538,12 @@ }, "minipass-flush": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-json-stream": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "dev": true, "requires": { "jsonparse": "^1.3.1", @@ -30933,37 +39552,25 @@ }, "minipass-pipeline": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, "requires": { "minipass": "^3.0.0" } }, "minipass-sized": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, "requires": { "minipass": "^3.0.0" } }, "minizlib": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" }, "dependencies": { "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "4.0.0" } } }, @@ -30994,17 +39601,16 @@ }, "mkdirp": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" } }, + "mkdirp-classic": { + "version": "0.5.3" + }, "mkdirp-infer-owner": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", - "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -31014,254 +39620,19 @@ "dependencies": { "mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "mocha": { - "version": "8.3.2", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "debug": { - "version": "4.3.1", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "dev": true - } - } - }, - "diff": { - "version": "5.0.0", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "dev": true - }, - "glob": { - "version": "7.1.6", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "js-yaml": { - "version": "4.0.0", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "ms": { - "version": "2.1.3", - "dev": true - }, - "nanoid": { - "version": "3.1.20", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "serialize-javascript": { - "version": "5.0.1", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.2", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "8.1.1", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.5", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", "dev": true } } }, "modify-values": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true }, "ms": { - "version": "2.0.0", - "dev": true + "version": "2.0.0" }, "multimatch": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", - "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", "dev": true, "requires": { "@types/minimatch": "^3.0.3", @@ -31273,26 +39644,25 @@ "dependencies": { "array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, "arrify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true } } }, "mute-stream": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nan": { + "version": "2.16.0" + }, "nanoid": { - "version": "3.1.18", + "version": "3.1.32", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.32.tgz", + "integrity": "sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==", "dev": true }, "nanomatch": { @@ -31318,45 +39688,70 @@ } } }, + "napi-build-utils": { + "version": "1.0.2" + }, "natural-compare": { "version": "1.4.0", "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true + "version": "0.6.2" }, "neo-async": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "nice-try": { "version": "1.0.5", "dev": true }, - "nise": { - "version": "1.5.0", - "dev": true, + "node-abi": { + "version": "3.22.0", "requires": { - "@sinonjs/formatio": "^3.1.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^4.1.0", - "path-to-regexp": "^1.7.0" + "semver": "^7.3.5" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.7", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0" + } } }, "node-fetch": { - "version": "2.6.1", - "dev": true + "version": "2.6.7", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3" + }, + "webidl-conversions": { + "version": "3.0.1" + }, + "whatwg-url": { + "version": "5.0.0", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } }, "node-gyp": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz", - "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==", "dev": true, "requires": { "env-paths": "^2.2.0", @@ -31374,14 +39769,10 @@ "dependencies": { "chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "fs-minipass": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "requires": { "minipass": "^2.6.0" @@ -31389,8 +39780,6 @@ }, "minipass": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -31399,8 +39788,6 @@ }, "minizlib": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "requires": { "minipass": "^2.9.0" @@ -31408,20 +39795,14 @@ }, "safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "tar": { "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dev": true, "requires": { "chownr": "^1.1.4", @@ -31435,8 +39816,6 @@ }, "which": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -31444,21 +39823,81 @@ }, "yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true } } }, - "node-preload": { - "version": "0.2.1", + "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-notifier": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz", + "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==", "dev": true, + "optional": true, "requires": { - "process-on-spawn": "^1.0.0" + "growly": "^1.3.0", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", + "shellwords": "^0.1.1", + "uuid": "^8.3.0", + "which": "^2.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "optional": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "optional": true + } } }, "node-releases": { - "version": "1.1.71", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "noms": { @@ -31471,8 +39910,6 @@ }, "nopt": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "requires": { "abbrev": "1", @@ -31495,14 +39932,10 @@ }, "normalize-url": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true }, "npm-bundled": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", "dev": true, "requires": { "npm-normalize-package-bin": "^1.0.1" @@ -31519,8 +39952,6 @@ }, "npm-install-checks": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", - "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", "dev": true, "requires": { "semver": "^7.1.1" @@ -31528,8 +39959,6 @@ "dependencies": { "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -31537,8 +39966,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -31546,16 +39973,12 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "npm-lifecycle": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz", - "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", "dev": true, "requires": { "byline": "^5.0.0", @@ -31570,8 +39993,6 @@ "dependencies": { "which": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -31581,24 +40002,10 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true }, - "npm-package-arg": { - "version": "6.1.0", - "dev": true, - "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", - "validate-npm-package-name": "^3.0.0" - } - }, "npm-packlist": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz", - "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==", "dev": true, "requires": { "glob": "^7.1.6", @@ -31609,8 +40016,6 @@ }, "npm-pick-manifest": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", - "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", "dev": true, "requires": { "npm-install-checks": "^4.0.0", @@ -31621,8 +40026,6 @@ "dependencies": { "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -31630,8 +40033,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -31639,8 +40040,6 @@ }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -31650,8 +40049,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -31659,16 +40056,12 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "npm-registry-fetch": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz", - "integrity": "sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==", "dev": true, "requires": { "@npmcli/ci-detect": "^1.0.0", @@ -31683,8 +40076,6 @@ "dependencies": { "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -31692,8 +40083,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -31701,8 +40090,6 @@ }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -31712,8 +40099,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -31721,8 +40106,6 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -31773,77 +40156,16 @@ } }, "number-is-nan": { - "version": "1.0.1", - "dev": true + "version": "1.0.1" }, - "nyc": { - "version": "15.1.0", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-map": { - "version": "3.0.0", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - } - } + "nwsapi": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", + "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", + "dev": true }, "oauth-sign": { "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { @@ -31904,8 +40226,6 @@ }, "object.getownpropertydescriptors": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "dev": true, "requires": { "call-bind": "^1.0.2", @@ -31922,15 +40242,12 @@ }, "once": { "version": "1.4.0", - "dev": true, "requires": { "wrappy": "1" } }, "onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" @@ -31938,8 +40255,6 @@ "dependencies": { "mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true } } @@ -31948,6 +40263,12 @@ "version": "1.6.2", "dev": true }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, "optionator": { "version": "0.9.1", "dev": true, @@ -31960,6 +40281,112 @@ "word-wrap": "^1.2.3" } }, + "ora": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz", + "integrity": "sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==", + "dev": true, + "requires": { + "bl": "^5.0.0", + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "strip-ansi": "^7.0.1", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "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 + }, + "bl": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", + "dev": true, + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "dev": true + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "os-homedir": { "version": "1.0.2", "dev": true @@ -32008,6 +40435,12 @@ "version": "1.1.0", "dev": true }, + "p-each-series": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", + "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", + "dev": true + }, "p-finally": { "version": "1.0.0", "dev": true @@ -32028,29 +40461,20 @@ }, "p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, "requires": { "aggregate-error": "^3.0.0" } }, "p-map-series": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", - "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", "dev": true }, "p-pipe": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz", - "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==", "dev": true }, "p-queue": { "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", "dev": true, "requires": { "eventemitter3": "^4.0.4", @@ -32059,22 +40483,16 @@ "dependencies": { "eventemitter3": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true } } }, "p-reduce": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", "dev": true }, "p-timeout": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", "dev": true, "requires": { "p-finally": "^1.0.0" @@ -32086,27 +40504,13 @@ }, "p-waterfall": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz", - "integrity": "sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==", "dev": true, "requires": { "p-reduce": "^2.0.0" } }, - "package-hash": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, "pacote": { "version": "11.3.5", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz", - "integrity": "sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg==", "dev": true, "requires": { "@npmcli/git": "^2.1.0", @@ -32132,8 +40536,6 @@ "dependencies": { "debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -32141,8 +40543,6 @@ }, "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -32150,8 +40550,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -32159,8 +40557,6 @@ }, "make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dev": true, "requires": { "agentkeepalive": "^4.1.3", @@ -32183,20 +40579,14 @@ }, "mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "npm-package-arg": { "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -32206,8 +40596,6 @@ }, "npm-registry-fetch": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", - "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", "dev": true, "requires": { "make-fetch-happen": "^9.0.1", @@ -32220,8 +40608,6 @@ }, "rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -32229,8 +40615,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -32238,8 +40622,6 @@ }, "socks-proxy-agent": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz", - "integrity": "sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==", "dev": true, "requires": { "agent-base": "^6.0.2", @@ -32249,27 +40631,27 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, "parent-module": { "version": "1.0.1", "dev": true, "requires": { "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "dev": true - } } }, "parse-github-url": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", "dev": true }, "parse-json": { @@ -32280,14 +40662,8 @@ "json-parse-better-errors": "^1.0.1" } }, - "parse-passwd": { - "version": "1.0.0", - "dev": true - }, "parse-path": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", - "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", "dev": true, "requires": { "is-ssh": "^1.3.0", @@ -32298,8 +40674,6 @@ }, "parse-url": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", - "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", "dev": true, "requires": { "is-ssh": "^1.3.0", @@ -32308,6 +40682,12 @@ "protocols": "^1.4.0" } }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, "pascalcase": { "version": "0.1.1", "dev": true @@ -32321,24 +40701,18 @@ "dev": true }, "path-is-absolute": { - "version": "1.0.1", - "dev": true + "version": "1.0.1" }, "path-key": { "version": "2.0.1", "dev": true }, "path-parse": { - "version": "1.0.6", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-to-regexp": { - "version": "1.7.0", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, "path-type": { "version": "3.0.0", "dev": true, @@ -32346,11 +40720,16 @@ "pify": "^3.0.0" } }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } }, "pend": { "version": "1.2.0", @@ -32366,20 +40745,22 @@ }, "performance-now": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "physical-cpu-count": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz", - "integrity": "sha1-GN4vl+S/epVRrXURlCtUlverpmA=", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "pidtree": { @@ -32390,66 +40771,64 @@ "version": "3.0.0", "dev": true }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, "pixi.js": { "version": "file:bundles/pixi.js", "requires": { - "@pixi/accessibility": "6.3.0", - "@pixi/app": "6.3.0", - "@pixi/compressed-textures": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/extract": "6.3.0", - "@pixi/filter-alpha": "6.3.0", - "@pixi/filter-blur": "6.3.0", - "@pixi/filter-color-matrix": "6.3.0", - "@pixi/filter-displacement": "6.3.0", - "@pixi/filter-fxaa": "6.3.0", - "@pixi/filter-noise": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/interaction": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/mixin-cache-as-bitmap": "6.3.0", - "@pixi/mixin-get-child-by-name": "6.3.0", - "@pixi/mixin-get-global-position": "6.3.0", - "@pixi/particle-container": "6.3.0", - "@pixi/polyfill": "6.3.0", - "@pixi/prepare": "6.3.0", - "@pixi/runner": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/sprite-animated": "6.3.0", - "@pixi/sprite-tiling": "6.3.0", - "@pixi/spritesheet": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/text-bitmap": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" + "@pixi/accessibility": "7.0.0-alpha", + "@pixi/app": "7.0.0-alpha", + "@pixi/assets": "7.0.0-alpha", + "@pixi/compressed-textures": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/events": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/extract": "7.0.0-alpha", + "@pixi/filter-alpha": "7.0.0-alpha", + "@pixi/filter-blur": "7.0.0-alpha", + "@pixi/filter-color-matrix": "7.0.0-alpha", + "@pixi/filter-displacement": "7.0.0-alpha", + "@pixi/filter-fxaa": "7.0.0-alpha", + "@pixi/filter-noise": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/mixin-cache-as-bitmap": "7.0.0-alpha", + "@pixi/mixin-get-child-by-name": "7.0.0-alpha", + "@pixi/mixin-get-global-position": "7.0.0-alpha", + "@pixi/particle-container": "7.0.0-alpha", + "@pixi/prepare": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/sprite-animated": "7.0.0-alpha", + "@pixi/sprite-tiling": "7.0.0-alpha", + "@pixi/spritesheet": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/text-bitmap": "7.0.0-alpha" } }, "pixi.js-legacy": { "version": "file:bundles/pixi.js-legacy", "requires": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-extract": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-particle-container": "6.3.0", - "@pixi/canvas-prepare": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-sprite-tiling": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "pixi.js": "6.3.0" + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-extract": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-particle-container": "7.0.0-alpha", + "@pixi/canvas-prepare": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-sprite-tiling": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "pixi.js": "7.0.0-alpha" } }, "pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { "find-up": "^4.0.0" @@ -32497,6 +40876,40 @@ } } }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, "posix-character-classes": { "version": "0.1.1", "dev": true @@ -32519,6 +40932,42 @@ } } }, + "prebuild-install": { + "version": "7.1.1", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "decompress-response": { + "version": "6.0.0", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "mimic-response": { + "version": "3.1.0" + }, + "simple-get": { + "version": "4.0.1", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + } + } + }, "prelude-ls": { "version": "1.2.1", "dev": true @@ -32527,44 +40976,74 @@ "version": "2.0.0", "dev": true }, - "process-nextick-args": { - "version": "2.0.0", - "dev": true - }, - "process-on-spawn": { - "version": "1.0.0", + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", "dev": true, "requires": { - "fromentries": "^1.2.0" + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + } } }, + "process-nextick-args": { + "version": "2.0.0", + "dev": true + }, "progress": { "version": "2.0.3", "dev": true }, "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "promise-polyfill": { - "version": "8.2.0" + "version": "1.0.1" }, "promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, "requires": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "promzard": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", "dev": true, "requires": { "read": "1" @@ -32576,8 +41055,6 @@ }, "protocols": { "version": "1.4.8", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", - "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==", "dev": true }, "pseudomap": { @@ -32586,32 +41063,48 @@ }, "psl": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, "pump": { "version": "3.0.0", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "dev": true }, "q": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qs": { "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", "dev": true, "requires": { "side-channel": "^1.0.4" @@ -32619,8 +41112,6 @@ }, "query-string": { "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", "dev": true, "requires": { "decode-uri-component": "^0.2.0", @@ -32634,21 +41125,30 @@ }, "quick-lru": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, - "randombytes": { - "version": "2.1.0", - "dev": true, + "rc": { + "version": "1.2.8", "requires": { - "safe-buffer": "^5.1.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1" + } } }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "read": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", "dev": true, "requires": { "mute-stream": "~0.0.4" @@ -32656,14 +41156,10 @@ }, "read-cmd-shim": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz", - "integrity": "sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==", "dev": true }, "read-package-json": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-3.0.1.tgz", - "integrity": "sha512-aLcPqxovhJTVJcsnROuuzQvv6oziQx4zd3JvG0vGCL5MjTONUc4uJ90zCBC6R7W7oUKBNoR/F8pkyfVwlbxqng==", "dev": true, "requires": { "glob": "^7.1.1", @@ -32674,8 +41170,6 @@ "dependencies": { "hosted-git-info": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -32683,8 +41177,6 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -32692,8 +41184,6 @@ }, "normalize-package-data": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", @@ -32704,8 +41194,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -32713,16 +41201,12 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "read-package-json-fast": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", "dev": true, "requires": { "json-parse-even-better-errors": "^2.3.0", @@ -32731,8 +41215,6 @@ }, "read-package-tree": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", - "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", "dev": true, "requires": { "read-package-json": "^2.0.0", @@ -32742,8 +41224,6 @@ "dependencies": { "read-package-json": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", - "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", "dev": true, "requires": { "glob": "^7.1.1", @@ -32756,8 +41236,6 @@ }, "read-pkg": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { "load-json-file": "^4.0.0", @@ -32767,8 +41245,6 @@ }, "read-pkg-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { "find-up": "^2.0.0", @@ -32777,8 +41253,6 @@ "dependencies": { "find-up": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -32788,7 +41262,6 @@ }, "readable-stream": { "version": "1.0.34", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -32798,8 +41271,6 @@ }, "readdir-scoped-modules": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", "dev": true, "requires": { "debuglog": "^1.0.1", @@ -32808,27 +41279,23 @@ "once": "^1.3.0" } }, - "readdirp": { - "version": "3.5.0", + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", "dev": true, "requires": { - "picomatch": "^2.2.1" + "util.promisify": "^1.0.0" } }, "redent": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, - "regenerate": { - "version": "1.4.0", - "dev": true - }, "regenerator-runtime": { "version": "0.13.7", "dev": true @@ -32842,27 +41309,15 @@ } }, "regexpp": { - "version": "3.1.0", + "version": "3.2.0", "dev": true }, - "regjsgen": { - "version": "0.5.0", + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "dev": true }, - "regjsparser": { - "version": "0.6.0", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - }, - "release-zalgo": { - "version": "1.0.0", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, "repeat-element": { "version": "1.1.2", "dev": true @@ -32873,8 +41328,6 @@ }, "request": { "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -32901,18 +41354,34 @@ "dependencies": { "qs": { "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, "safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "dev": true, + "requires": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "dev": true @@ -32921,8 +41390,14 @@ "version": "1.0.1", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "resolve": { - "version": "1.10.0", + "version": "1.17.0", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -32930,8 +41405,6 @@ }, "resolve-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "requires": { "resolve-from": "^5.0.0" @@ -32939,20 +41412,10 @@ "dependencies": { "resolve-from": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true } } }, - "resolve-dir": { - "version": "1.0.1", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, "resolve-from": { "version": "4.0.0", "dev": true @@ -32970,8 +41433,6 @@ }, "restore-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "requires": { "onetime": "^5.1.0", @@ -32983,10 +41444,7 @@ "dev": true }, "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", - "dev": true + "version": "0.12.0" }, "reusify": { "version": "1.0.4", @@ -33020,14 +41478,60 @@ } }, "rollup": { - "version": "2.70.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", - "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", + "version": "2.77.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz", + "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==", "dev": true, "requires": { "fsevents": "~2.3.2" } }, + "rollup-plugin-esbuild": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-4.9.1.tgz", + "integrity": "sha512-qn/x7Wz9p3Xnva99qcb+nopH0d2VJwVnsxJTGEg+Sh2Z3tqQl33MhOwzekVo1YTKgv+yAmosjcBRJygMfGrtLw==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^4.1.1", + "debug": "^4.3.3", + "es-module-lexer": "^0.9.3", + "joycon": "^3.0.1", + "jsonc-parser": "^3.0.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "rollup-plugin-jscc": { "version": "2.0.0", "dev": true, @@ -33065,26 +41569,6 @@ "rollup-pluginutils": "^2.4.1" } }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - } - }, - "rollup-plugin-typescript": { - "version": "1.0.1", - "dev": true, - "requires": { - "resolve": "^1.10.0", - "rollup-pluginutils": "^2.5.0" - } - }, "rollup-pluginutils": { "version": "2.6.0", "dev": true, @@ -33093,10 +41577,14 @@ "micromatch": "^3.1.10" } }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, "run-async": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true }, "run-parallel": { @@ -33105,16 +41593,15 @@ }, "rxjs": { "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "safe-buffer": { - "version": "5.1.1", - "dev": true + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -33125,6 +41612,99 @@ }, "safer-buffer": { "version": "2.1.2", + "devOptional": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "sax": { + "version": "1.2.4" + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true }, "semver": { @@ -33151,18 +41731,8 @@ } } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "set-blocking": { - "version": "2.0.0", - "dev": true + "version": "2.0.0" }, "set-value": { "version": "2.0.0", @@ -33185,8 +41755,6 @@ }, "shallow-clone": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -33194,8 +41762,6 @@ "dependencies": { "kind-of": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true } } @@ -33215,10 +41781,15 @@ "version": "1.7.2", "dev": true }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true, + "optional": true + }, "side-channel": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "requires": { "call-bind": "^1.0.0", @@ -33227,28 +41798,35 @@ } }, "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true + "version": "3.0.7" }, - "sinon": { - "version": "7.3.2", - "dev": true, + "simple-concat": { + "version": "1.0.1" + }, + "simple-get": { + "version": "3.1.1", "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.1", - "diff": "^3.5.0", - "lolex": "^4.0.1", - "nise": "^1.4.10", - "supports-color": "^5.5.0" + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "4.2.1", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "mimic-response": { + "version": "2.1.0" + } } }, - "sinon-chai": { - "version": "3.3.0", - "dev": true, - "requires": {} + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true }, "skip-regex": { "version": "1.0.2", @@ -33256,8 +41834,6 @@ }, "slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "slice-ansi": { @@ -33277,15 +41853,10 @@ }, "slide": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true + "version": "4.2.0" }, "snapdragon": { "version": "0.8.2", @@ -33374,19 +41945,14 @@ } }, "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", - "dev": true, + "version": "2.6.2", "requires": { "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "smart-buffer": "^4.2.0" } }, "socks-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", "dev": true, "requires": { "agent-base": "^6.0.2", @@ -33396,8 +41962,6 @@ "dependencies": { "debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" @@ -33405,8 +41969,6 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } @@ -33435,8 +41997,6 @@ }, "source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -33459,45 +42019,6 @@ "os-shim": "^0.1.2" } }, - "spawn-wrap": { - "version": "2.0.0", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "6.3.0", - "dev": true - }, - "which": { - "version": "2.0.2", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, "spdx-correct": { "version": "3.1.0", "dev": true, @@ -33511,7 +42032,7 @@ "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", + "version": "3.0.1", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -33524,8 +42045,6 @@ }, "split": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "requires": { "through": "2" @@ -33533,8 +42052,6 @@ }, "split-on-first": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", "dev": true }, "split-string": { @@ -33546,8 +42063,6 @@ }, "split2": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "requires": { "readable-stream": "^3.0.0" @@ -33555,8 +42070,6 @@ "dependencies": { "readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -33566,14 +42079,10 @@ }, "safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { "safe-buffer": "~5.2.0" @@ -33587,8 +42096,6 @@ }, "sshpk": { "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -33604,13 +42111,27 @@ }, "ssri": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, "requires": { "minipass": "^3.1.1" } }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, "static-extend": { "version": "0.1.2", "dev": true, @@ -33628,23 +42149,58 @@ } } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "strict-uri-encode": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", "dev": true }, "string_decoder": { - "version": "0.10.31", - "dev": true + "version": "0.10.31" }, "string-argv": { "version": "0.3.1", "dev": true }, + "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, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "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 + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "string-width": { "version": "1.0.2", - "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -33678,7 +42234,6 @@ }, "strip-ansi": { "version": "3.0.1", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -33693,14 +42248,10 @@ }, "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 }, "strip-indent": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "requires": { "min-indent": "^1.0.0" @@ -33712,8 +42263,6 @@ }, "strong-log-transformer": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", "dev": true, "requires": { "duplexer": "^0.1.1", @@ -33748,6 +42297,45 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "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 + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "5.4.6", "dev": true, @@ -33790,9 +42378,6 @@ }, "tar": { "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -33803,23 +42388,58 @@ }, "dependencies": { "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "version": "1.0.4" }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "4.0.0" + } + } + }, + "tar-fs": { + "version": "2.1.1", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "chownr": { + "version": "1.1.4" + } + } + }, + "tar-stream": { + "version": "2.2.0", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1" + }, + "string_decoder": { + "version": "1.3.0", + "requires": { + "safe-buffer": "~5.2.0" + } } } }, "task-graph-runner": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/task-graph-runner/-/task-graph-runner-1.0.3.tgz", - "integrity": "sha512-aC70bepv1j9jXX70nzolNvnHJvD4A3WtU4lQ1HEjgTS8rgnRXoUUq+xl9hZ1hKYXxVwElZXmUUMxpzDC6R0mRg==", "dev": true, "requires": { "array-includes": "^3.0.3" @@ -33827,14 +42447,10 @@ }, "temp-dir": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", "dev": true }, "temp-write": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz", - "integrity": "sha512-HIeWmj77uOOHb0QX7siN3OtwV3CTntquin6TNVg6SHOqCP3hYKmox90eeFOGaY1MqJ9WYDDjkyZrW6qS5AWpbw==", "dev": true, "requires": { "graceful-fs": "^4.1.15", @@ -33846,51 +42462,18 @@ "dependencies": { "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 - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, - "terser": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", - "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", "dev": true, "requires": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" } }, "test-exclude": { @@ -33904,14 +42487,18 @@ }, "text-extensions": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, "text-table": { "version": "0.2.0", "dev": true }, + "throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "dev": true + }, "through": { "version": "2.3.8", "dev": true @@ -33961,6 +42548,12 @@ "os-tmpdir": "~1.0.2" } }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "dev": true @@ -33996,8 +42589,6 @@ }, "tough-cookie": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { "psl": "^1.1.28", @@ -34006,8 +42597,6 @@ }, "tr46": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", "dev": true, "requires": { "punycode": "^2.1.1" @@ -34015,10 +42604,64 @@ }, "trim-newlines": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "ts-jest": { + "version": "26.5.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", + "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^26.1.0", + "json5": "2.x", + "lodash": "4.x", + "make-error": "1.x", + "mkdirp": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, "ts-node": { "version": "9.0.0", "dev": true, @@ -34046,11 +42689,13 @@ } }, "tslib": { - "version": "1.9.3", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tsutils": { - "version": "3.18.0", + "version": "3.21.0", "dev": true, "requires": { "tslib": "^1.8.1" @@ -34063,17 +42708,12 @@ }, "tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, "type-check": { @@ -34085,8 +42725,6 @@ }, "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 }, "type-fest": { @@ -34105,7 +42743,7 @@ } }, "typescript": { - "version": "3.9.5", + "version": "4.3.5", "dev": true }, "uc.micro": { @@ -34114,21 +42752,15 @@ }, "uglify-js": { "version": "3.14.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", - "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", "dev": true, "optional": true }, "uid-number": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "dev": true }, "umask": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", "dev": true }, "unbox-primitive": { @@ -34141,22 +42773,15 @@ "which-boxed-primitive": "^1.0.2" } }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "qs": "^6.4.0" } }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "dev": true - }, "union-value": { "version": "1.0.0", "dev": true, @@ -34192,26 +42817,18 @@ }, "unique-filename": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, "requires": { "unique-slug": "^2.0.0" } }, "unique-slug": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, "universal-user-agent": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", "dev": true }, "universalify": { @@ -34256,10 +42873,18 @@ }, "upath": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", - "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.2.2", "dev": true, @@ -34283,6 +42908,12 @@ } } }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, "url-parse-lax": { "version": "3.0.0", "dev": true, @@ -34295,18 +42926,28 @@ "dev": true }, "util-deprecate": { - "version": "1.0.2", - "dev": true + "version": "1.0.2" }, "util-promisify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", - "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", "dev": true, "requires": { "object.getownpropertydescriptors": "^2.0.3" } }, + "util.promisify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", + "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "for-each": "^0.3.3", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.1" + } + }, "uuid": { "version": "3.4.0", "dev": true @@ -34315,6 +42956,25 @@ "version": "2.1.1", "dev": true }, + "v8-to-istanbul": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz", + "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, "validate-npm-package-license": { "version": "3.0.4", "dev": true, @@ -34331,13 +42991,11 @@ } }, "validator": { - "version": "8.2.0", + "version": "13.7.0", "dev": true }, "verror": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -34345,10 +43003,35 @@ "extsprintf": "^1.2.0" } }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, "wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "requires": { "defaults": "^1.0.3" @@ -34356,14 +43039,16 @@ }, "webidl-conversions": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", "dev": true }, "whatwg-url": { "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", "dev": true, "requires": { "lodash": "^4.7.0", @@ -34395,7 +43080,6 @@ }, "wide-align": { "version": "1.1.3", - "dev": true, "requires": { "string-width": "^1.0.2 || 2" } @@ -34406,18 +43090,10 @@ }, "wordwrap": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "workerpool": { - "version": "6.1.0", "dev": true }, "workspaces-run": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/workspaces-run/-/workspaces-run-1.0.1.tgz", - "integrity": "sha512-B7tZj/g4/1JCeNQ7+zVNVBC83hOJBKpOm/yYob3eqw0Aerp1Guecfdf0J6kO/I/EyA2X2uP1oCHWsh2QywXh0A==", "dev": true, "requires": { "aggregate-error": "^3.0.1", @@ -34439,8 +43115,6 @@ "dependencies": { "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" @@ -34448,8 +43122,6 @@ }, "braces": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { "fill-range": "^7.0.1" @@ -34457,8 +43129,6 @@ }, "chalk": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -34467,8 +43137,6 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" @@ -34476,8 +43144,6 @@ }, "cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -34487,8 +43153,6 @@ }, "fill-range": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -34496,20 +43160,14 @@ }, "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 }, "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 }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" @@ -34517,8 +43175,6 @@ }, "meow": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", - "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -34536,16 +43192,12 @@ "dependencies": { "type-fest": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true } } }, "micromatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", @@ -34554,8 +43206,6 @@ }, "p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -34563,14 +43213,10 @@ }, "p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -34581,14 +43227,10 @@ }, "path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "read-pkg": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { "@types/normalize-package-data": "^2.4.0", @@ -34599,16 +43241,12 @@ "dependencies": { "type-fest": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true } } }, "read-pkg-up": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { "find-up": "^4.1.0", @@ -34618,8 +43256,6 @@ }, "semver": { "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -34627,8 +43263,6 @@ }, "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" @@ -34636,14 +43270,10 @@ }, "shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -34651,8 +43281,6 @@ }, "to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "is-number": "^7.0.0" @@ -34660,8 +43288,6 @@ }, "which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -34669,9 +43295,17 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -34685,8 +43319,6 @@ }, "wrapline": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wrapline/-/wrapline-2.0.1.tgz", - "integrity": "sha1-x5kIrBX0HUAdpmB/8lZh1MkUebs=", "dev": true, "requires": { "duplexer2": "~0.0.2", @@ -34696,14 +43328,10 @@ "dependencies": { "object-keys": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, "split2": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-0.1.2.tgz", - "integrity": "sha1-pNVguR8EFo8hzZvdVptveNUWRZM=", "dev": true, "requires": { "through2": "~0.4.1" @@ -34711,8 +43339,6 @@ "dependencies": { "through2": { "version": "0.4.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", - "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", "dev": true, "requires": { "readable-stream": "~1.0.17", @@ -34721,8 +43347,6 @@ }, "xtend": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dev": true, "requires": { "object-keys": "~0.4.0" @@ -34732,8 +43356,6 @@ }, "through2": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { "readable-stream": "~1.0.17", @@ -34742,15 +43364,12 @@ }, "xtend": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", "dev": true } } }, "wrappy": { - "version": "1.0.2", - "dev": true + "version": "1.0.2" }, "write": { "version": "1.0.3", @@ -34768,30 +43387,37 @@ "signal-exit": "^3.0.2" } }, - "write-json-file": { - "version": "2.3.0", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "pify": "^3.0.0", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.0.0" - } + "ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "dev": true }, - "write-pkg": { - "version": "3.2.0", - "dev": true, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml2js": { + "version": "0.4.23", "requires": { - "sort-keys": "^2.0.0", - "write-json-file": "^2.2.0" + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" } }, - "xtend": { - "version": "4.0.1", + "xmlbuilder": { + "version": "11.0.1" + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xtend": { + "version": "4.0.1" + }, "y18n": { "version": "3.2.1", "dev": true @@ -34802,8 +43428,6 @@ }, "yaml": { "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true }, "yargs": { @@ -34894,40 +43518,24 @@ "y18n": { "version": "4.0.3", "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, "yargs-parser": { - "version": "18.1.3", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "dev": true - } - } + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true }, "yauzl": { "version": "2.10.0", @@ -34941,18 +43549,14 @@ "version": "3.1.1", "dev": true }, - "yocto-queue": { - "version": "0.1.0", - "dev": true - }, "z-schema": { - "version": "3.18.4", + "version": "5.0.2", "dev": true, "requires": { "commander": "^2.7.1", - "lodash.get": "^4.0.0", - "lodash.isequal": "^4.0.0", - "validator": "^8.0.0" + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" } } } diff --git a/package.json b/package.json index 4359a6601a6..db759215040 100644 --- a/package.json +++ b/package.json @@ -4,38 +4,33 @@ "workspaces": [ "bundles/*", "packages/*", - "packages/canvas/*", - "packages/filters/*", "tools/*" ], "scripts": { "start": "run-s watch", - "clean:build": "rimraf \"{bundles,packages,packages/canvas,packages/filters,out}/*/dist\"", + "clean:build": "rimraf \"{bundles,packages,out}/*/dist\"", + "clean:types": "rimraf \"{bundles,packages}/*/index.d.ts\"", "clean:dist": "rimraf dist/*", "clean:modules": "lerna clean --yes", "clean": "run-s clean:*", - "floss": "cross-env TS_NODE_PROJECT=tsconfig.tests.json floss -r ts-node/register/transpile-only -p test", - "test": "run-s lint:tests floss", - "unit-test": "npm run floss -- --", - "unit-test:debug": "npm run floss -- --debug --", - "precoverage": "run-s lint:tests", - "coverage": "nyc run-s floss && nyc report --reporter=html", - "coverage:ci": "run-s coverage && nyc report --reporter=text-lcov > coverage.lcov", + "test:pkg": "ts-node --transpile-only ./test/index.ts", + "test:pkg:debug": "cross-env DEBUG_MODE=1 ts-node --transpile-only ./test/index.ts", + "test": "npx jest --silent", + "test:debug": "cross-env DEBUG_MODE=1 npx jest", + "coverage": "npm run test -- --coverage --maxWorkers=4", "docs": "mkdirp dist && webdoc -R README.md", - "lint:src": "eslint --ext .js --ext .ts test bundles packages scripts --ignore-path .gitignore --ignore-pattern \"**/*.tests.ts\" --max-warnings 0", - "lint:tests": "eslint -c .eslintrc.tests.json --ext .ts \"**/*.tests.ts\" --max-warnings 0", - "lint": "run-s lint:*", - "lintfix": "run-s \"lint:* -- --fix\"", + "lint": "eslint --ext .js --ext .ts test bundles packages scripts --ignore-path .gitignore --max-warnings 0", + "lintfix": "run-s \"lint -- --fix\"", "types": "tsc -noEmit", "build": "run-s clean:build build:dev", "build:prod": "cross-env NODE_ENV=production rollup -c", "build:dev": "rollup -c", "build:types": "rimraf out && tsc && api-extractor-lerna-monorepo && rimraf out && ts-node-script ./scripts/injectGlobalMixins.ts", "watch": "rollup -cw", - "dist": "run-s lint:src types build:prod build:types docs", - "postdist": "copyfiles -f bundles/*/dist/browser/* dist && copyfiles -f \"packages/**/dist/browser/*\" dist/packages", + "dist": "run-s lint types build:prod build:types docs", + "postdist": "copyfiles -f bundles/*/dist/browser/* dist", "prerelease": "run-s clean:build test", - "postversion": "run-s lint:src types build:prod build:types", + "postversion": "run-s lint types build:prod build:types", "release": "lerna version --exact --force-publish", "version": "ts-node scripts/fixPeerVersions.ts && npx --yes npm@7.20.2 i --package-lock-only && git add package-lock.json", "prepublish-ci": "run-s build:types", @@ -46,58 +41,48 @@ "lintfix" ], "engines": { - "node": ">=12", + "node": ">=14", "yarn": "please-use-npm", "npm": ">=7" }, - "nyc": { - "all": true, - "extends": "@istanbuljs/nyc-config-typescript", - "include": [ - "packages/**/src/**" - ], - "exclude": [ - "packages/polyfill/src**" - ], - "report-dir": "dist/coverage" - }, "devDependencies": { - "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@microsoft/api-extractor": "^7.9.11", - "@pixi-build-tools/api-extractor-lerna-monorepo": "^1.0.3", - "@pixi/eslint-config": "^2.0.1", + "@microsoft/api-extractor": "~7.20.1", + "@pixi-build-tools/api-extractor-lerna-monorepo": "~1.1.0", + "@pixi/eslint-config": "^4.0.1", "@pixi/webdoc-template": "^1.5.3", "@rollup/plugin-alias": "^3.1.1", - "@rollup/plugin-buble": "^0.21.3", "@rollup/plugin-commonjs": "^15.1.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^9.0.0", - "@rollup/plugin-typescript": "^6.0.0", - "@types/mocha": "^8.2.3", - "@webdoc/cli": "^1.5.5", - "chai": "~4.3.6", + "@types/css-font-loading-module": "^0.0.7", + "@types/jest": "^26.0.0", + "@webdoc/cli": "^2.0.0", "copyfiles": "^2.1.0", "cross-env": "^5.2.0", "electron": "^12.0.0", + "esbuild": "^0.14.48", "eslint": "^7.2.0", - "floss": "^5.0.0", + "eslint-plugin-jsdoc": "^39.2.9", "glob": "^7.1.3", + "http-server": "^14.1.1", + "jest": "^26.0.0", + "jest-electron": "^0.1.12", + "jest-extended": "^1.2.1", + "jest-raw-loader": "^1.0.1", "lerna": "^4.0.0", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", "pre-commit": "^1.2.2", "rimraf": "^2.6.3", - "rollup": "^2.70.1", + "rollup": "^2.75.7", + "rollup-plugin-esbuild": "^4.9.1", "rollup-plugin-jscc": "^2.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "rollup-plugin-string": "^3.0.0", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-typescript": "^1.0.1", - "sinon": "^7.3.2", - "sinon-chai": "^3.3.0", + "ts-jest": "^26.0.0", "ts-node": "^9.0.0", "tsconfig-paths": "^3.10.1", - "typescript": "^3.9.5", - "workspaces-run": "^1.0.1" + "typescript": "~4.3.0", + "workspaces-run": "^1.0.1", + "yargs-parser": "^21.0.1" } } diff --git a/packages/accessibility/README.md b/packages/accessibility/README.md index fb3ef18601f..ed3ead0f587 100644 --- a/packages/accessibility/README.md +++ b/packages/accessibility/README.md @@ -9,8 +9,5 @@ npm install @pixi/accessibility ## Usage ```js -import { AccessibilityManager } from '@pixi/accessibility'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('accessibility', AccessibilityManager); +import '@pixi/accessibility'; ``` \ No newline at end of file diff --git a/packages/accessibility/package.json b/packages/accessibility/package.json index c7dbcd0b424..3ee77d4f08f 100644 --- a/packages/accessibility/package.json +++ b/packages/accessibility/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/accessibility", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/accessibility.js", - "module": "dist/esm/accessibility.js", - "bundle": "dist/browser/accessibility.js", + "module": "dist/esm/accessibility.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/accessibility.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/accessibility.js" + } + } + }, "description": "Accessibility Plugin for visually impaired users", "author": "Mat Groves", "contributors": [ @@ -20,13 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/events" + ] } diff --git a/packages/accessibility/src/AccessibilityManager.ts b/packages/accessibility/src/AccessibilityManager.ts index 7644a4f27c4..3a2c226976f 100644 --- a/packages/accessibility/src/AccessibilityManager.ts +++ b/packages/accessibility/src/AccessibilityManager.ts @@ -1,11 +1,11 @@ import { DisplayObject } from '@pixi/display'; -import { isMobile, removeItems } from '@pixi/utils'; import { accessibleTarget } from './accessibleTarget'; -import type { Rectangle } from '@pixi/math'; import type { Container } from '@pixi/display'; -import type { Renderer, AbstractRenderer } from '@pixi/core'; +import { ExtensionType, extensions, utils } from '@pixi/core'; import type { IAccessibleHTMLElement } from './accessibleTarget'; +import type { Rectangle, IRenderer, ExtensionMetadata } from '@pixi/core'; +import { FederatedEvent } from '@pixi/events'; // add some extra variables to the container.. DisplayObject.mixin(accessibleTarget); @@ -30,21 +30,28 @@ const DIV_HOOK_ZINDEX = 2; * events as if the mouse was being used, minimizing the effort required to implement. * * An instance of this class is automatically created by default, and can be found at `renderer.plugins.accessibility` - * * @class * @memberof PIXI */ export class AccessibilityManager { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'accessibility', + type: [ + ExtensionType.RendererPlugin, + ExtensionType.CanvasRendererPlugin, + ], + }; + /** Setting this to true will visually show the divs. */ public debug = false; /** * The renderer this accessibility manager works for. - * * @type {PIXI.CanvasRenderer|PIXI.Renderer} */ - public renderer: AbstractRenderer|Renderer; + public renderer: IRenderer; /** Internal variable, see isActive getter. */ private _isActive = false; @@ -76,11 +83,11 @@ export class AccessibilityManager /** * @param {PIXI.CanvasRenderer|PIXI.Renderer} renderer - A reference to the current renderer */ - constructor(renderer: AbstractRenderer|Renderer) + constructor(renderer: IRenderer) { this._hookDiv = null; - if (isMobile.tablet || isMobile.phone) + if (utils.isMobile.tablet || utils.isMobile.phone) { this.createTouchHook(); } @@ -100,7 +107,6 @@ export class AccessibilityManager /** * pre-bind the functions - * * @type {Function} * @private */ @@ -108,7 +114,6 @@ export class AccessibilityManager /** * pre-bind the functions - * * @type {Function} * @private */ @@ -140,7 +145,6 @@ export class AccessibilityManager /** * Creates the touch hooks. - * * @private */ private createTouchHook(): void @@ -169,7 +173,6 @@ export class AccessibilityManager /** * Destroys the touch hooks. - * * @private */ private destroyTouchHook(): void @@ -185,7 +188,6 @@ export class AccessibilityManager /** * Activating will cause the Accessibility layer to be shown. * This is called when a user presses the tab key. - * * @private */ private activate(): void @@ -207,7 +209,6 @@ export class AccessibilityManager /** * Deactivating will cause the Accessibility layer to be hidden. * This is called when a user moves the mouse. - * * @private */ private deactivate(): void @@ -228,7 +229,6 @@ export class AccessibilityManager /** * This recursive function will run through the scene graph and add any new accessible objects to the DOM layer. - * * @private * @param {PIXI.Container} displayObject - The DisplayObject to check. */ @@ -262,7 +262,6 @@ export class AccessibilityManager /** * Before each render this function will ensure that all divs are mapped correctly to their DisplayObjects. - * * @private */ private update(): void @@ -273,22 +272,22 @@ export class AccessibilityManager */ const now = performance.now(); - if (isMobile.android.device && now < this.androidUpdateCount) + if (utils.isMobile.android.device && now < this.androidUpdateCount) { return; } this.androidUpdateCount = now + this.androidUpdateFrequency; - if (!(this.renderer as Renderer).renderingToScreen) + if (!this.renderer.renderingToScreen) { return; } // update children... - if (this.renderer._lastObjectRendered) + if (this.renderer.lastObjectRendered) { - this.updateAccessibleObjects(this.renderer._lastObjectRendered as Container); + this.updateAccessibleObjects(this.renderer.lastObjectRendered as Container); } const { left, top, width, height } = this.renderer.view.getBoundingClientRect(); @@ -312,7 +311,7 @@ export class AccessibilityManager { child._accessibleActive = false; - removeItems(this.children, i, 1); + utils.removeItems(this.children, i, 1); this.div.removeChild(child._accessibleDiv); this.pool.push(child._accessibleDiv); child._accessibleDiv = null; @@ -375,8 +374,7 @@ export class AccessibilityManager /** * private function that will visually add the information to the * accessability div - * - * @param {HTMLElement} div + * @param {HTMLElement} div - */ public updateDebugHTML(div: IAccessibleHTMLElement): void { @@ -385,7 +383,6 @@ export class AccessibilityManager /** * Adjust the hit area based on the bounds of a display object - * * @param {PIXI.Rectangle} hitArea - Bounds of the child */ public capHitArea(hitArea: Rectangle): void @@ -417,7 +414,6 @@ export class AccessibilityManager /** * Adds a DisplayObject to the accessibility manager - * * @private * @param {PIXI.DisplayObject} displayObject - The child to make accessible. */ @@ -439,7 +435,7 @@ export class AccessibilityManager div.style.borderStyle = 'none'; // ARIA attributes ensure that button title and hint updates are announced properly - if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) + if (navigator.userAgent.toLowerCase().includes('chrome')) { // Chrome doesn't need aria-live to work as intended; in fact it just gets more confused. div.setAttribute('aria-live', 'off'); @@ -498,25 +494,33 @@ export class AccessibilityManager } /** - * Maps the div button press to pixi's InteractionManager (click) - * + * Dispatch events with the EventSystem. + * @param e + * @param type + * @private + */ + private _dispatchEvent(e: UIEvent, type: string[]): void + { + const { displayObject: target } = e.target as IAccessibleHTMLElement; + const boundry = this.renderer.events.rootBoundary; + const event: FederatedEvent = Object.assign(new FederatedEvent(boundry), { target }); + + boundry.rootTarget = this.renderer.lastObjectRendered as DisplayObject; + type.forEach((type) => boundry.dispatchEvent(event, type)); + } + + /** + * Maps the div button press to pixi's EventSystem (click) * @private * @param {MouseEvent} e - The click event. */ private _onClick(e: MouseEvent): void { - const interactionManager = this.renderer.plugins.interaction; - const { displayObject } = e.target as IAccessibleHTMLElement; - const { eventData } = interactionManager; - - interactionManager.dispatchEvent(displayObject, 'click', eventData); - interactionManager.dispatchEvent(displayObject, 'pointertap', eventData); - interactionManager.dispatchEvent(displayObject, 'tap', eventData); + this._dispatchEvent(e, ['click', 'pointertap', 'tap']); } /** - * Maps the div focus events to pixi's InteractionManager (mouseover) - * + * Maps the div focus events to pixi's EventSystem (mouseover) * @private * @param {FocusEvent} e - The focus event. */ @@ -527,16 +531,11 @@ export class AccessibilityManager (e.target as Element).setAttribute('aria-live', 'assertive'); } - const interactionManager = this.renderer.plugins.interaction; - const { displayObject } = e.target as IAccessibleHTMLElement; - const { eventData } = interactionManager; - - interactionManager.dispatchEvent(displayObject, 'mouseover', eventData); + this._dispatchEvent(e, ['mouseover']); } /** - * Maps the div focus events to pixi's InteractionManager (mouseout) - * + * Maps the div focus events to pixi's EventSystem (mouseout) * @private * @param {FocusEvent} e - The focusout event. */ @@ -547,16 +546,11 @@ export class AccessibilityManager (e.target as Element).setAttribute('aria-live', 'polite'); } - const interactionManager = this.renderer.plugins.interaction; - const { displayObject } = e.target as IAccessibleHTMLElement; - const { eventData } = interactionManager; - - interactionManager.dispatchEvent(displayObject, 'mouseout', eventData); + this._dispatchEvent(e, ['mouseout']); } /** * Is called when a key is pressed - * * @private * @param {KeyboardEvent} e - The keydown event. */ @@ -572,7 +566,6 @@ export class AccessibilityManager /** * Is called when the mouse moves across the renderer element - * * @private * @param {MouseEvent} e - The mouse event. */ @@ -586,10 +579,7 @@ export class AccessibilityManager this.deactivate(); } - /** - * Destroys the accessibility manager - * - */ + /** Destroys the accessibility manager */ public destroy(): void { this.destroyTouchHook(); @@ -603,3 +593,5 @@ export class AccessibilityManager this.renderer = null; } } + +extensions.add(AccessibilityManager); diff --git a/packages/accessibility/src/accessibleTarget.ts b/packages/accessibility/src/accessibleTarget.ts index 8718ef0a5f6..c5a50d9ca67 100644 --- a/packages/accessibility/src/accessibleTarget.ts +++ b/packages/accessibility/src/accessibleTarget.ts @@ -12,7 +12,8 @@ export type PointerEvents = 'auto' | 'all' | 'inherit'; -export interface IAccessibleTarget { +export interface IAccessibleTarget +{ accessible: boolean; accessibleTitle: string; accessibleHint: string; @@ -25,7 +26,8 @@ export interface IAccessibleTarget { renderId: number; } -export interface IAccessibleHTMLElement extends HTMLElement { +export interface IAccessibleHTMLElement extends HTMLElement +{ type?: string; displayObject?: DisplayObject; } @@ -33,11 +35,10 @@ export interface IAccessibleHTMLElement extends HTMLElement { /** * Default property values of accessible objects * used by {@link PIXI.AccessibilityManager}. - * * @private * @function accessibleTarget * @memberof PIXI - * @type {Object} + * @type {object} * @example * function MyObject() {} * @@ -50,7 +51,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Flag for if the object is accessible. If true AccessibilityManager will overlay a * shadow div with attributes set - * * @member {boolean} * @memberof PIXI.DisplayObject# */ @@ -59,7 +59,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Sets the title attribute of the shadow div * If accessibleTitle AND accessibleHint has not been this will default to 'displayObject [tabIndex]' - * * @member {?string} * @memberof PIXI.DisplayObject# */ @@ -67,7 +66,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Sets the aria-label attribute of the shadow div - * * @member {string} * @memberof PIXI.DisplayObject# */ @@ -98,7 +96,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Specify the type of div the accessible layer is. Screen readers treat the element differently * depending on this type. Defaults to button. - * * @member {string} * @memberof PIXI.DisplayObject# * @default 'button' @@ -108,7 +105,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Specify the pointer-events the accessible div will use * Defaults to auto. - * * @member {string} * @memberof PIXI.DisplayObject# * @default 'auto' @@ -118,7 +114,6 @@ export const accessibleTarget: IAccessibleTarget = { /** * Setting to false will prevent any children inside this container to * be accessible. Defaults to true. - * * @member {boolean} * @memberof PIXI.DisplayObject# * @default true diff --git a/packages/accessibility/test/AccessibilityManager.tests.ts b/packages/accessibility/test/AccessibilityManager.tests.ts index 15887c41d49..3226fa5aeb4 100644 --- a/packages/accessibility/test/AccessibilityManager.tests.ts +++ b/packages/accessibility/test/AccessibilityManager.tests.ts @@ -3,61 +3,62 @@ import { CanvasRenderer } from '@pixi/canvas-renderer'; import { DisplayObject, Container } from '@pixi/display'; import { Renderer } from '@pixi/core'; import { isMobile } from '@pixi/utils'; -import { expect } from 'chai'; -describe('AccessibilityManager', function () +describe('AccessibilityManager', () => { - it('should exist', function () + it('should exist', () => { - expect(AccessibilityManager).to.be.not.undefined; + expect(AccessibilityManager).toBeDefined(); }); - it('should create new manager', function () + it('should create new manager', () => { - const manager = new AccessibilityManager(); + const manager = new AccessibilityManager(undefined); - expect(manager).to.be.instanceof(AccessibilityManager); + expect(manager).toBeInstanceOf(AccessibilityManager); manager.destroy(); }); - it('should be plugin for renderer', function () + it('should be plugin for renderer', () => { - CanvasRenderer.registerPlugin('accessibility', AccessibilityManager); - const renderer = new CanvasRenderer(); - expect(renderer.plugins.accessibility).to.be.instanceof(AccessibilityManager); + expect(renderer.plugins.accessibility).toBeInstanceOf(AccessibilityManager); renderer.destroy(); }); - it('should remove touch hook when destroyed', function () + it('should remove touch hook when destroyed', () => { const phone = isMobile.phone; isMobile.phone = true; - const manager = new AccessibilityManager(); - const hookDiv = manager._hookDiv; + const manager = new AccessibilityManager(undefined); + const hookDiv = manager['_hookDiv']; - expect(hookDiv).to.be.instanceof(HTMLElement); - expect(document.body.contains(hookDiv)).to.be.true; + expect(hookDiv).toBeInstanceOf(HTMLElement); + expect(document.body.contains(hookDiv)).toBe(true); manager.destroy(); - expect(document.body.contains(hookDiv)).to.be.false; + expect(document.body.contains(hookDiv)).toBe(false); isMobile.phone = phone; }); - it('should activate when tab is pressed and deactivate when mouse moved', function () + it('should activate when tab is pressed and deactivate when mouse moved', () => { const renderer = new Renderer(); const manager = new AccessibilityManager(renderer); globalThis.dispatchEvent(new KeyboardEvent('keydown', { keyCode: 9, key: 'tab' })); - expect(manager.isActive).to.be.true; - globalThis.document.dispatchEvent(new MouseEvent('mousemove', { movementX: 10, movementY: 10 })); - expect(manager.isActive).to.be.false; + setTimeout(() => + { + expect(manager.isActive).toBe(true); + globalThis.document.dispatchEvent(new MouseEvent('mousemove', { movementX: 10, movementY: 10 })); + expect(manager.isActive).toBe(false); + }, 0); }); - it('should not crash when scene graph contains DisplayObjects without children', function () + it('should not crash when scene graph contains DisplayObjects without children', () => { + // @ts-expect-error - mock DisplayObject class CompleteDisplayObject extends DisplayObject { calculateBounds() { /* noop */ } @@ -70,7 +71,10 @@ describe('AccessibilityManager', function () globalThis.dispatchEvent(new KeyboardEvent('keydown', { keyCode: 9, key: 'tab' })); - expect(() => renderer.render(stage)).not.to.throw(); - expect(manager.isActive).to.be.true; + expect(() => renderer.render(stage)).not.toThrowError(); + setTimeout(() => + { + expect(manager.isActive).toBe(true); + }, 0); }); }); diff --git a/packages/accessibility/test/accessibleTarget.tests.ts b/packages/accessibility/test/accessibleTarget.tests.ts index 6d1a3409628..37b45327f60 100644 --- a/packages/accessibility/test/accessibleTarget.tests.ts +++ b/packages/accessibility/test/accessibleTarget.tests.ts @@ -1,18 +1,17 @@ import { DisplayObject } from '@pixi/display'; -import { expect } from 'chai'; - import '@pixi/accessibility'; -describe('accessibleTarget', function () +describe('accessibleTarget', () => { - it('should have target public properties', function () + it('should have target public properties', () => { + // @ts-expect-error --- const obj = new DisplayObject(); - expect(obj.accessible).to.be.a('boolean'); - expect(obj.accessible).to.be.false; - expect(obj.accessibleTitle).to.be.null; - expect(obj.accessibleHint).to.be.null; - expect(obj.tabIndex).to.equal(0); + expect(obj.accessible).toBeBoolean(); + expect(obj.accessible).toBe(false); + expect(obj.accessibleTitle).toBeNull(); + expect(obj.accessibleHint).toBeNull(); + expect(obj.tabIndex).toEqual(0); }); }); diff --git a/packages/app/README.md b/packages/app/README.md index e3a8e9d7600..f932d7e8646 100644 --- a/packages/app/README.md +++ b/packages/app/README.md @@ -17,7 +17,6 @@ document.body.appendChild(app.view); ### Plugins -PixiJS provides a few plugins to add features to the Application. These can be installed from the following packages. Use `Application.registerPlugin` to use these plugins. _Note: if you are using pixi.js or pixi.js-legacy bundles, this is unnecessary since plugins are installed automatically by default._ +PixiJS provides a few plugins to add features to the Application. These can be installed from the following packages. Use `extensions.add` to use these plugins. _Note: if you are using pixi.js or pixi.js-legacy bundles, this is unnecessary since plugins are installed automatically by default._ -* **LoaderPlugin** from `@pixi/loaders` -* **TickerPlugin** from `@pixi/ticker` \ No newline at end of file +* **TickerPlugin** from `@pixi/ticker` diff --git a/packages/app/global.d.ts b/packages/app/global.d.ts index 7998a3c5b48..7be0741b72a 100644 --- a/packages/app/global.d.ts +++ b/packages/app/global.d.ts @@ -1,15 +1,15 @@ declare namespace GlobalMixins { - // eslint-disable-next-line @typescript-eslint/no-empty-interface interface Application { - resizeTo: Window|HTMLElement; + resizeTo: Window | HTMLElement; resize(): void; + queueResize: () => void; + cancelResize: () => void; } - // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IApplicationOptions { - resizeTo?: Window|HTMLElement; + resizeTo?: Window | HTMLElement; } } diff --git a/packages/app/package.json b/packages/app/package.json index 509ac0da9a4..f02e0ffa3a7 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/app", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/app.js", - "module": "dist/esm/app.js", - "bundle": "dist/browser/app.js", + "module": "dist/esm/app.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/app.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/app.js" + } + } + }, "description": "Convenience class to create a new PixiJS application", "author": "Mat Groves", "contributors": [ @@ -20,12 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/app/src/Application.ts b/packages/app/src/Application.ts index 5e333a30e44..eac812af7c7 100644 --- a/packages/app/src/Application.ts +++ b/packages/app/src/Application.ts @@ -1,25 +1,22 @@ import { Container } from '@pixi/display'; -import { autoDetectRenderer } from '@pixi/core'; +import { autoDetectRenderer, extensions, ExtensionType } from '@pixi/core'; -import type { Rectangle } from '@pixi/math'; -import type { Renderer, IRendererOptionsAuto, AbstractRenderer } from '@pixi/core'; +import type { Rectangle, IRendererOptionsAuto, IRenderer } from '@pixi/core'; import type { IDestroyOptions } from '@pixi/display'; /** * Any plugin that's usable for Application should contain these methods. * @memberof PIXI - * @see {@link PIXI.Application.registerPlugin} */ -export interface IApplicationPlugin { +export interface IApplicationPlugin +{ /** * Called when Application is constructed, scoped to Application instance. * Passes in `options` as the only argument, which are Application constructor options. * @param {object} options - Application options. */ init(options: IApplicationOptions): void; - /** - * Called when destroying Application, scoped to Application instance. - */ + /** Called when destroying Application, scoped to Application instance. */ destroy(): void; } @@ -33,7 +30,6 @@ export interface Application extends GlobalMixins.Application {} * Convenience class to create a new PIXI application. * * This class automatically creates the renderer, ticker and root container. - * * @example * // Create the application * const app = new PIXI.Application(); @@ -43,14 +39,13 @@ export interface Application extends GlobalMixins.Application {} * * // ex, add display objects * app.stage.addChild(PIXI.Sprite.from('something.png')); - * * @class * @memberof PIXI */ export class Application { /** Collection of installed plugins. */ - private static _plugins: IApplicationPlugin[] = []; + static _plugins: IApplicationPlugin[] = []; /** * The root display container that's rendered. @@ -62,7 +57,7 @@ export class Application * WebGL renderer if available, otherwise CanvasRenderer. * @member {PIXI.Renderer|PIXI.CanvasRenderer} */ - public renderer: Renderer|AbstractRenderer; + public renderer: IRenderer; /** * @param {object} [options] - The optional renderer parameters. @@ -113,19 +108,7 @@ export class Application }); } - /** - * Register a middleware plugin for the application - * @static - * @param {PIXI.IApplicationPlugin} plugin - Plugin being installed - */ - static registerPlugin(plugin: IApplicationPlugin): void - { - Application._plugins.push(plugin); - } - - /** - * Render the current stage. - */ + /** Render the current stage. */ public render(): void { this.renderer.render(this.stage); @@ -153,7 +136,7 @@ export class Application /** * Destroy and don't use after this. - * @param {Boolean} [removeView=false] - Automatically remove canvas from DOM. + * @param {boolean} [removeView=false] - Automatically remove canvas from DOM. * @param {object|boolean} [stageOptions] - Options parameter. A boolean will act as if all options * have been set to that value * @param {boolean} [stageOptions.children=false] - if set to true, all the children will have their destroy @@ -163,7 +146,7 @@ export class Application * @param {boolean} [stageOptions.baseTexture=false] - Only used for child Sprites if stageOptions.children is set * to true. Should it destroy the base texture of the child sprite */ - public destroy(removeView?: boolean, stageOptions?: IDestroyOptions|boolean): void + public destroy(removeView?: boolean, stageOptions?: IDestroyOptions | boolean): void { // Destroy plugins in the opposite order // which they were constructed @@ -182,3 +165,5 @@ export class Application this.renderer = null; } } + +extensions.handleByList(ExtensionType.Application, Application._plugins); diff --git a/packages/app/src/ResizePlugin.ts b/packages/app/src/ResizePlugin.ts index 53ef096ebba..a2e705b7d3f 100644 --- a/packages/app/src/ResizePlugin.ts +++ b/packages/app/src/ResizePlugin.ts @@ -1,7 +1,9 @@ -import type { CanvasRenderer } from '@pixi/canvas-renderer'; -import type { Renderer } from '@pixi/core'; +import type { ExtensionMetadata, Renderer } from '@pixi/core'; +import { extensions, ExtensionType } from '@pixi/core'; import type { IApplicationOptions } from './Application'; +type ResizeableRenderer = Pick; + /** * Middleware for for Application's resize functionality * @private @@ -9,12 +11,15 @@ import type { IApplicationOptions } from './Application'; */ export class ResizePlugin { - public static resizeTo: Window|HTMLElement; + /** @ignore */ + static extension: ExtensionMetadata = ExtensionType.Application; + + public static resizeTo: Window | HTMLElement; public static resize: () => void; - public static renderer: Renderer|CanvasRenderer; + public static renderer: ResizeableRenderer; public static queueResize: () => void; private static _resizeId: number; - private static _resizeTo: Window|HTMLElement; + private static _resizeTo: Window | HTMLElement; private static cancelResize: () => void; /** @@ -34,7 +39,7 @@ export class ResizePlugin * @memberof PIXI.Application# */ { - set(dom: Window|HTMLElement) + set(dom: Window | HTMLElement) { globalThis.removeEventListener('resize', this.queueResize); this._resizeTo = dom; @@ -53,7 +58,6 @@ export class ResizePlugin /** * Resize is throttled, so it's safe to call this multiple times per frame and it'll * only be called once. - * * @memberof PIXI.Application# * @method queueResize * @private @@ -73,7 +77,6 @@ export class ResizePlugin /** * Cancel the resize queue. - * * @memberof PIXI.Application# * @method cancelResize * @private @@ -91,7 +94,6 @@ export class ResizePlugin * Execute an immediate resize on the renderer, this is not * throttled and can be expensive to call many times in a row. * Will resize only if `resizeTo` property is set. - * * @memberof PIXI.Application# * @method resize */ @@ -134,7 +136,6 @@ export class ResizePlugin /** * Clean up the ticker, scoped to application - * * @static * @private */ @@ -148,3 +149,5 @@ export class ResizePlugin this.resize = null; } } + +extensions.add(ResizePlugin); diff --git a/packages/app/src/index.ts b/packages/app/src/index.ts index f19a4ebbc50..aa069933586 100644 --- a/packages/app/src/index.ts +++ b/packages/app/src/index.ts @@ -1,6 +1,2 @@ -import { Application } from './Application'; -import { ResizePlugin } from './ResizePlugin'; - -Application.registerPlugin(ResizePlugin); - export * from './Application'; +export * from './ResizePlugin'; diff --git a/packages/app/test/Application.tests.ts b/packages/app/test/Application.tests.ts index 28e1982bc32..2311b10a628 100644 --- a/packages/app/test/Application.tests.ts +++ b/packages/app/test/Application.tests.ts @@ -1,122 +1,118 @@ import { Application } from '@pixi/app'; -import { autoDetectRenderer } from '@pixi/canvas-renderer'; -import { Container, DisplayObject } from '@pixi/display'; -import { skipHello } from '@pixi/utils'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { extensions, ExtensionType, utils } from '@pixi/core'; +import { Container } from '@pixi/display'; -skipHello(); +utils.skipHello(); -// Use fallback if no webgl -Application.prototype.createRenderer = autoDetectRenderer; - -describe('Application', function () +describe('Application', () => { - it('should generate application', function () + it('should generate application', () => { - expect(Application).to.be.a('function'); + expect(Application).toBeInstanceOf(Function); const app = new Application(); - expect(app.stage).to.be.instanceof(Container); - expect(app.renderer).to.be.ok; + expect(app.stage).toBeInstanceOf(Container); + expect(app.renderer).toBeTruthy(); app.destroy(); - expect(app.stage).to.be.null; - expect(app.renderer).to.be.null; + expect(app.stage).toBeNull(); + expect(app.renderer).toBeNull(); }); - it('register a new plugin, then destroy it', function () + it('register a new plugin, then destroy it', () => { const plugin = { - init: sinon.spy(), - destroy: sinon.spy(), + init: jest.fn(), + destroy: jest.fn(), }; + const extension = { type: ExtensionType.Application, ref: plugin }; - Application.registerPlugin(plugin); + extensions.add(extension); const app = new Application(); app.destroy(); - expect(plugin.init).to.be.calledOnce; - expect(plugin.destroy).to.be.calledOnce; + expect(plugin.init).toHaveBeenCalledOnce(); + expect(plugin.destroy).toHaveBeenCalledOnce(); - Application._plugins.pop(); + extensions.remove(extension); }); - it('should remove canvas when destroyed', function () + it('should remove canvas when destroyed', () => { const app = new Application(); const view = app.view; - expect(view).to.be.instanceof(HTMLCanvasElement); + expect(view).toBeInstanceOf(HTMLCanvasElement); document.body.appendChild(view); - expect(document.body.contains(view)).to.be.true; + expect(document.body.contains(view)).toBe(true); app.destroy(true); - expect(document.body.contains(view)).to.be.false; + expect(document.body.contains(view)).toBe(false); }); - it('should not destroy children by default', function () + it('should not destroy children by default', () => { const app = new Application(); const stage = app.stage; - const child = new DisplayObject(); + const child = new Container(); stage.addChild(child); app.destroy(true); - expect(child.transform).to.not.be.null; + expect(child.transform).not.toBeNull(); }); - it('should allow children destroy', function () + it('should allow children destroy', () => { const app = new Application(); const stage = app.stage; - const child = new DisplayObject(); + const child = new Container(); stage.addChild(child); app.destroy(true, true); - expect(child.transform).to.be.null; + expect(child.transform).toBeNull(); }); - describe('resizeTo', function () + describe('resizeTo', () => { - before(function () + let div: HTMLDivElement; + + beforeAll(() => { - const div = document.createElement('div'); + div = document.createElement('div'); div.style.width = '100px'; div.style.height = '200px'; document.body.appendChild(div); - this.div = div; }); - after(function () + afterAll(() => { - this.div.parentNode.removeChild(this.div); - this.div = null; + div.parentNode.removeChild(div); + div = null; }); - it('should assign resizeTo', function () + it('should assign resizeTo', () => { const app = new Application({ - resizeTo: this.div, + resizeTo: div, }); - expect(app.resizeTo).to.equal(this.div); - expect(app.view.width).to.equal(100); - expect(app.view.height).to.equal(200); + expect(app.resizeTo).toEqual(div); + expect(app.view.width).toEqual(100); + expect(app.view.height).toEqual(200); app.destroy(); }); - it('should force multiple immediate resizes', function () + it('should force multiple immediate resizes', () => { - const spy = sinon.spy(); + const spy = jest.fn(); const app = new Application({ - resizeTo: this.div, + resizeTo: div, }); app.renderer.on('resize', spy); @@ -124,16 +120,16 @@ describe('Application', function () app.resize(); app.resize(); - expect(spy.calledTwice).to.be.true; + expect(spy).toBeCalledTimes(2); app.destroy(); }); - it('should throttle multiple resizes', function (done) + it('should throttle multiple resizes', (done) => { - const spy = sinon.spy(); + const spy = jest.fn(); const app = new Application({ - resizeTo: this.div, + resizeTo: div, }); app.renderer.on('resize', spy); @@ -142,17 +138,17 @@ describe('Application', function () setTimeout(() => { - expect(spy.calledOnce).to.be.true; + expect(spy).toBeCalledTimes(1); app.destroy(); done(); }, 50); }); - it('should cancel resize on destroy', function (done) + it('should cancel resize on destroy', (done) => { - const spy = sinon.spy(); + const spy = jest.fn(); const app = new Application({ - resizeTo: this.div, + resizeTo: div, }); app.renderer.on('resize', spy); @@ -161,16 +157,16 @@ describe('Application', function () requestAnimationFrame(() => { - expect(spy.called).to.be.false; + expect(spy).not.toBeCalled(); done(); }); }); - it('should resize cancel resize queue', function (done) + it('should resize cancel resize queue', (done) => { - const spy = sinon.spy(); + const spy = jest.fn(); const app = new Application({ - resizeTo: this.div, + resizeTo: div, }); app.renderer.on('resize', spy); @@ -180,35 +176,35 @@ describe('Application', function () requestAnimationFrame(() => { - expect(spy.calledOnce).to.be.true; + expect(spy).toBeCalledTimes(1); done(); }); }); - it('should resizeTo with resolution', function () + it('should resizeTo with resolution', () => { const app = new Application({ resolution: 2, - resizeTo: this.div, + resizeTo: div, }); - expect(app.view.width).to.equal(200); - expect(app.view.height).to.equal(400); + expect(app.view.width).toEqual(200); + expect(app.view.height).toEqual(400); app.destroy(); }); - it('should resizeTo with resolution and autoDensity', function () + it('should resizeTo with resolution and autoDensity', () => { const app = new Application({ resolution: 2, - resizeTo: this.div, + resizeTo: div, autoDensity: true, }); - expect(app.view.width).to.equal(200); - expect(app.view.height).to.equal(400); - expect(app.view.style.width).to.equal(this.div.style.width); - expect(app.view.style.height).to.equal(this.div.style.height); + expect(app.view.width).toEqual(200); + expect(app.view.height).toEqual(400); + expect(app.view.style.width).toEqual(div.style.width); + expect(app.view.style.height).toEqual(div.style.height); app.destroy(); }); }); diff --git a/packages/assets/README.md b/packages/assets/README.md new file mode 100644 index 00000000000..e05dfb21df2 --- /dev/null +++ b/packages/assets/README.md @@ -0,0 +1,10 @@ +# @pixi/assets + +This package contains the assets class for PixiJS +managing the resolving and loading of assets. + +## Installation + +```bash +npm install @pixi/assets +``` diff --git a/packages/assets/package.json b/packages/assets/package.json new file mode 100644 index 00000000000..b58e228b47e --- /dev/null +++ b/packages/assets/package.json @@ -0,0 +1,49 @@ +{ + "name": "@pixi/assets", + "version": "7.0.0-alpha", + "description": "Asset manager for PixiJS, loading resolving and Cacheing", + "keywords": [ + "pixi", + "caching", + "resolving", + "loaders" + ], + "author": "Mat Groves ", + "homepage": "https://github.com/pixijs/pixi.js#readme", + "license": "MIT", + "main": "dist/cjs/assets.js", + "module": "dist/esm/assets.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/assets.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/assets.js" + } + } + }, + "publishConfig": { + "access": "public" + }, + "files": [ + "dist", + "*.d.ts" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/pixijs/pixi.js.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/pixijs/pixi.js/issues" + }, + "pixiRequirements": [ + "@pixi/core" + ] +} diff --git a/packages/assets/src/Assets.ts b/packages/assets/src/Assets.ts new file mode 100644 index 00000000000..0207edb2138 --- /dev/null +++ b/packages/assets/src/Assets.ts @@ -0,0 +1,794 @@ +import { extensions, ExtensionType } from '@pixi/core'; +import { BackgroundLoader } from './BackgroundLoader'; +import { Cache } from './cache/Cache'; +import type { FormatDetectionParser } from './detections'; +import type { + LoadAsset, + LoaderParser +} from './loader'; +import { Loader } from './loader/Loader'; +import type { PreferOrder, ResolveAsset, ResolverBundle, ResolverManifest, ResolveURLParser } from './resolver'; +import { Resolver } from './resolver/Resolver'; +import { convertToList } from './utils/convertToList'; +import { isSingleItem } from './utils/isSingleItem'; + +export type ProgressCallback = (progress: number) => void; + +/** + * Initialization options object for Asset Class. + * @memberof PIXI + */ +export interface AssetInitOptions +{ + // basic... + /** a base path for any assets loaded */ + basePath?: string; + /** + * a manifest to tell the asset loader upfront what all your assets are + * this can be the manifest object itself, or a URL to the manifest. + */ + manifest?: string | ResolverManifest; + /** + * optional preferences for which textures preferences you have when resolving assets + * for example you might set the resolution to 0.5 if the user is on a rubbish old phone + * or you might set the resolution to 2 if the user is on a retina display + */ + texturePreference?: { + /** the resolution order you prefer, can be an array (priority order - first is prefered) or a single resolutions */ + resolution?: number | number[]; + /** the formats you prefer, by default this will be: ['avif', 'webp', 'png', 'jpg', 'jpeg'] */ + format?: string | string[]; + }; + + // advanced users can add custom parsers and and preferences for how things are resolved + /** loader options to configure the loader with, currently only parsers! */ + loader?: { + /** custom parsers can be added here, for example something that could load a sound or a 3D model */ + parsers?: LoaderParser[]; + // more... + }; + /** resolver specific options */ + resolver?: { + /** + * a list of urlParsers, these can read the URL and pick put the various options. + * for example there is a texture URL parser that picks our resolution and file format. + * You can add custom ways to read URLs and extract information here. + */ + urlParsers?: ResolveURLParser[]; + /** + * a list of preferOrders that let the resolver know which asset to pick. + * already built-in we have a texture preferOrders that let the resolve know which asset to prefer + * if it has multiple assets to pick from (resolution/formats etc) + */ + preferOrders?: PreferOrder[]; + }; +} + +/** + * A one stop shop for all Pixi resource management! + * Super modern and easy to use, with enough flexibility to customize and do what you need! + * @memberof PIXI + * @namespace Assets + * + * Only one Asset Class exists accessed via the Global Asset object. + * + * It has four main responsibilities: + * 1. Allows users to map URLs to keys and resolve them according to the user's browser capabilities + * 2. Loads the resources and transforms them into assets that developers understand. + * 3. Caches the assets and provides a way to access them. + * 4: Allow developers to unload assets and clear the cache. + * + * It also has a few advanced features: + * 1. Allows developers to provide a manifest upfront of all assets and help manage them via 'bundles' + * 2. Allows users to background load assets. Shortening (or eliminating) load times and improving UX. With this feature, + * in-game loading bars can be a thing of the past! + * + * + * Do not be afraid to load things multiple times - under the hood, it will NEVER load anything more than once. + * + * for example: + * + * ``` + * promise1 = PIXI.Assets.load('bunny.png') + * promise2 = PIXI.Assets.load('bunny.png') + * + * //promise1 === promise2 + * ``` + * here both promises will be the same. Once resolved.. forever resolved! It makes for really easy resource management! + * + * Out of the box it supports the following files: + * * textures (avif, webp, png, jpg, gif) + * * sprite sheets (json) + * * bitmap fonts (xml, fnt, txt) + * * web fonts (ttf, woff, woff2) + * * json files (json) + * * text files (txt) + * + * More types can be added fairly easily by creating additional loader parsers. + * + * ### Textures + * - Textures are loaded as ImageBitmap on a worker thread where possible. + * Leading to much less janky load + parse times. + * - By default, we will prefer to load AVIF and WebP image files if you specify them. + * But if the browser doesn't support AVIF or WebP we will fall back to png and jpg. + * - Textures can also be accessed via Texture.from(...) and now use this asset manager under the hood! + * - Don't worry if you set preferences for textures that don't exist (for example you prefer 2x resolutions images + * but only 1x is available for that texture, the Asset manager will pick that up as a fallback automatically) + * #### Sprite sheets + * - it's hard to know what resolution a sprite sheet is without loading it first, to address this + * there is a naming convention we have added that will let Pixi understand the image format and resolution + * of the spritesheet via its file name: + * + * `my-spritesheet{resolution}.{imageFormat}.json` + * + * for example: + * + * `my-spritesheet@2x.webp.json` // 2x resolution, WebP sprite sheet + * `my-spritesheet@0.5x.png.json` // 0.5x resolution, png sprite sheet + * + * This is optional! you can just load a sprite sheet as normal, + * This is only useful if you have a bunch of different res / formatted spritesheets + * + * ### Fonts + * * Web fonts will be loaded with all weights. + * it is possible to load only specific weights by doing the following: + * + * ``` + * // load specific weights.. + * await PIXI.Assets.load({ + * data: { + * weights: ['normal'], // only loads the weight + * }, + * src: `outfit.woff2`, + * }); + * + * // load everything... + * await PIXI.Assets.load(`outfit.woff2`); + * ``` + * ### Background Loading + * Background loading will load stuff for you passively behind the scenes. To minimize jank, + * it will only load one asset at a time. As soon as a developer calls `PIXI.Assets.load(...)` the + * background loader is paused and requested assets are loaded as a priority. + * Don't worry if something is in there that's already loaded, it will just get skipped! + * + * You still need to call `PIXI.Assets.load(...)` to get an asset that has been loaded in the background. + * It's just that this promise will resolve instantly if the asset + * has already been loaded. + * + * ### Manifest and Bundles + * - Manifest is a JSON file that contains a list of all assets and their properties. + * - Bundles are a way to group assets together. + * + * ``` + * // manifest example + * const manifest = { + * bundles:[{ + * name:'load-screen', + * assets:[ + * { + * name: 'background', + * srcs: 'sunset.png', + * }, + * { + * name: 'bar', + * srcs: 'load-bar.{png,webp}', + * } + * ] + * }, + * { + * name:'game-screen', + * assets:[ + * { + * name: 'character', + * srcs: 'robot.png', + * }, + * { + * name: 'enemy', + * srcs: 'bad-guy.png', + * } + * ] + * }] + * }} + * + * await PIXI.Asset.init({ + * manifest + * }); + * + * // load a bundle.. + * loadScreenAssets = await PIXI.Assets.loadBundle('load-screen'); + * // load another.. + * gameScreenAssets = await PIXI.Assets.loadBundle('game-screen'); + * ``` + * @example + * const bunny = await PIXI.Assets.load('bunny.png'); + */ +export class AssetsClass +{ + /** the resolver to map various urls */ + public resolver: Resolver; + /** + * The loader, loads stuff! + * @type {PIXI.AssetLoader} + */ + public loader: Loader; + /** + * The global cache of all assets within PixiJS + * @type {PIXI.Cache} + */ + public cache: typeof Cache; + + /** takes care of loading assets in the background */ + private readonly _backgroundLoader: BackgroundLoader; + + private _detections: FormatDetectionParser[] = []; + + private _initialized = false; + + constructor() + { + this.resolver = new Resolver(); + this.loader = new Loader(); + this.cache = Cache; + + this._backgroundLoader = new BackgroundLoader(this.loader); + this._backgroundLoader.active = true; + + this.reset(); + } + + /** + * Best practice is to call this function before any loading commences + * Initiating is the best time to add any customization to the way things are loaded. + * + * you do not need to call this for the Asset class to work, only if you want to set any initial properties + * @param options - options to initialize the Asset manager with + */ + public async init(options: AssetInitOptions = {}): Promise + { + if (this._initialized) + { + // #if _DEBUG + console.warn('[Assets]AssetManager already initialized, did you load before calling this Asset.init()?'); + // #endif + + return; + } + + this._initialized = true; + + if (options.basePath) + { + this.resolver.basePath = options.basePath; + } + + if (options.manifest) + { + let manifest = options.manifest; + + if (typeof manifest === 'string') + { + manifest = await this.load(manifest) as ResolverManifest; + } + + this.resolver.addManifest(manifest); + } + + const resolutionPref = options.texturePreference?.resolution ?? 1; + const resolution = (typeof resolutionPref === 'number') ? [resolutionPref] : resolutionPref; + + let formats: string[] = []; + + if (options.texturePreference?.format) + { + const formatPref = options.texturePreference?.format; + + formats = (typeof formatPref === 'string') ? [formatPref] : formatPref; + + // we should remove any formats that are not supported by the browser + for (const detection of this._detections) + { + if (!await detection.test()) + { + formats = await detection.remove(formats); + } + } + } + else + { + // we should add any formats that are supported by the browser + for (const detection of this._detections) + { + if (await detection.test()) + { + formats = await detection.add(formats); + } + } + } + + this.resolver.prefer({ + params: { + format: formats, + resolution, + }, + }); + } + + /** + * Allows you to specify how to resolve any assets load requests. + * There are a few ways to add things here as shown below: + * @example + * // simple + * PIXI.Assets.add('bunnyBooBoo', 'bunny.png'); + * const bunny = await PIXI.Assets.load('bunnyBooBoo'); + * + * // multiple keys: + * PIXI.Assets.add(['burger', 'chicken'], 'bunny.png'); + * + * const bunny = await PIXI.Assets.load('burger'); + * const bunny2 = await PIXI.Assets.load('chicken'); + * + * // passing options to to the object + * PIXI.Assets.add( + * 'bunnyBooBooSmooth', + * 'bunny{png,webp}', + * {scaleMode:SCALE_MODES.NEAREST} // base texture options + * ); + * + * // multiple assets, + * + * // the following all do the same thing: + * + * PIXI.Assets.add('bunnyBooBoo', 'bunny{png,webp}'); + * + * PIXI.Assets.add('bunnyBooBoo', [ + * 'bunny.png', + * 'bunny.webp' + * ]); + * + * PIXI.Assets.add('bunnyBooBoo', [ + * { + * format:'png', + * src:'bunny.png', + * }, + * { + * format:'webp', + * src:'bunny.webp', + * } + * ]); + * + * const bunny = await PIXI.Assets.load('bunnyBooBoo'); // will try to load WebP if available + * @param keysIn - the key or keys that you will reference when loading this asset + * @param assetsIn - the asset or assets that will be chosen from when loading via the specified key + * @param data - asset-specific data that will be passed to the loaders + * - Useful if you want to initiate loaded objects with specific data + */ + public add(keysIn: string | string[], assetsIn: string | (ResolveAsset | string)[], data?: unknown): void + { + this.resolver.add(keysIn, assetsIn, data); + } + + /** + * Loads your assets! You pass in a key or URL and it will return a promise that + * resolves to the loaded asset. If multiple assets a requested, it will return a hash of assets. + * + * Don't worry about loading things multiple times, behind the scenes assets are only ever loaded + * once and the same promise reused behind the scenes so you can safely call this function multiple + * times with the same key and it will always return the same asset. + * @example + * // load a URL: + * const myImageTexture = await PIXI.Assets.load('http://some.url.com/image.png'); // => returns a texture + * + * PIXI.Assets.add('thumper', 'bunny.png'); + * PIXI.Assets.add('chicko', 'chicken.png'); + * + * // load multiple assets: + * const textures = await PIXI.Assets.load(['thumper', 'chicko']); // => {thumper: Texture, chicko: Texture} + * @param urls - the urls to load + * @param onProgress - optional function that is called when progress on asset loading is made. + * The function is passed a single parameter, `progress`, which represents the percentage + * (0.0 - 1.0) of the assets loaded. + * @returns - the assets that were loaded, either a single asset or a hash of assets + */ + public async load( + urls: string | string[] | LoadAsset | LoadAsset[], + onProgress?: ProgressCallback, + ): Promise> + { + if (!this._initialized) + { + await this.init(); + } + + const singleAsset = isSingleItem(urls); + + const urlArray = convertToList(urls) + .map((url) => + { + if (typeof url !== 'string') + { + this.resolver.add(url.src as string, url); + + return url.src; + } + + return url; + }); + + // check cache first... + const resolveResults = this.resolver.resolve(urlArray); + + // remap to the keys used.. + const out: Record = await this._mapLoadToResolve(resolveResults, onProgress); + + return singleAsset ? out[urlArray[0] as string] : out; + } + + /** + * This adds a bundle of assets in one go so that you can load them as a group. + * For example you could add a bundle for each screen in you pixi app + * @example + * PIXI.Assets.addBundle('animals', { + * bunny: 'bunny.png', + * chicken: 'chicken.png', + * thumper: 'thumper.png', + * }); + * + * const assets = await PIXI.Assets.loadBundle('animals'); + * @param bundleId - the id of the bundle to add + * @param assets - a record of the asset or assets that will be chosen from when loading via the specified key + */ + public addBundle(bundleId: string, assets: ResolverBundle['assets']): void + { + this.resolver.addBundle(bundleId, assets); + } + + /** + * Bundles are a way to load multiple assets at once. + * If a manifest has been provided to the init function then you can load a bundle, or bundles. + * you can also add bundles via `addBundle` + * @example + * // manifest example + * const manifest = { + * bundles:[{ + * name:'load-screen', + * assets:[ + * { + * name: 'background', + * srcs: 'sunset.png', + * }, + * { + * name: 'bar', + * srcs: 'load-bar.{png,webp}', + * } + * ] + * }, + * { + * name:'game-screen', + * assets:[ + * { + * name: 'character', + * srcs: 'robot.png', + * }, + * { + * name: 'enemy', + * srcs: 'bad-guy.png', + * } + * ] + * }] + * }} + * + * await Asset.init({ + * manifest + * }); + * + * // load a bundle.. + * loadScreenAssets = await PIXI.Assets.loadBundle('load-screen'); + * // load another.. + * gameScreenAssets = await PIXI.Assets.loadBundle('game-screen'); + * @param bundleIds - the bundle id or ids to load + * @param onProgress - optional function that is called when progress on asset loading is made. + * The function is passed a single parameter, `progress`, which represents the percentage (0.0 - 1.0) + * of the assets loaded. + * @returns all the bundles assets or a hash of assets for each bundle specified + */ + public async loadBundle(bundleIds: string | string[], onProgress?: ProgressCallback): Promise + { + if (!this._initialized) + { + await this.init(); + } + + let singleAsset = false; + + if (typeof bundleIds === 'string') + { + singleAsset = true; + bundleIds = [bundleIds]; + } + + const resolveResults = this.resolver.resolveBundle(bundleIds); + + const out: Record> = {}; + + const keys = Object.keys(resolveResults); + let count = 0; + let total = 0; + const _onProgress = () => + { + onProgress?.(++count / total); + }; + const promises = keys.map((bundleId) => + { + const resolveResult = resolveResults[bundleId]; + + total += Object.keys(resolveResult).length; + + return this._mapLoadToResolve(resolveResult, _onProgress) + .then((resolveResult) => + { + out[bundleId] = resolveResult; + }); + }); + + await Promise.all(promises); + + return singleAsset ? out[bundleIds[0]] : out; + } + + /** + * Initiate a background load of some assets. it will passively begin to load these assets in the background. + * So when you actually come to loading them you will get a promise that resolves to the loaded assets immediately + * + * An example of this might be that you would background load game assets after your inital load. + * then when you got to actually load your game screen assets when a player goes to the game - the loading + * would already have stared or may even be complete, saving you having to show an interim load bar. + * @example + * PIXI.Assets.backgroundLoad('bunny.png'); + * + * // later on in your app... + * await PIXI.Assets.loadBundle('bunny.png'); // will resolve quicker as loading may have completed! + * @param urls - the url / urls you want to background load + */ + public async backgroundLoad(urls: string | string[]): Promise + { + if (!this._initialized) + { + await this.init(); + } + + if (typeof urls === 'string') + { + urls = [urls]; + } + + const resolveResults = this.resolver.resolve(urls); + + this._backgroundLoader.add(Object.values(resolveResults)); + } + + /** + * Initiate a background of a bundle, works exactly like backgroundLoad but for bundles. + * this can only be used if the loader has been initiated with a manifest + * @example + * await PIXI.Assets.init({ + * manifest: { + * bundles: [ + * { + * name:'load-screen', + * assets:[...] + * } + * ...] + * } + * }); + * + * PIXI.Assets.backgroundLoadBundle('load-screen'); + * + * // later on in your app... + * await PIXI.Assets.loadBundle('load-screen'); // will resolve quicker as loading may have completed! + * @param bundleIds - the bundleId / bundleIds you want to background load + */ + public async backgroundLoadBundle(bundleIds: string | string[]): Promise + { + if (!this._initialized) + { + await this.init(); + } + + if (typeof bundleIds === 'string') + { + bundleIds = [bundleIds]; + } + + const resolveResults = this.resolver.resolveBundle(bundleIds); + + Object.values(resolveResults).forEach((resolveResult) => + { + this._backgroundLoader.add(Object.values(resolveResult)); + }); + } + + /** + * Only intended for development purposes. + * This will wipe the resolver and caches. + * You will need to reinitialize the Asset + */ + public reset(): void + { + this.resolver.reset(); + this.loader.reset(); + this.cache.reset(); + + this._initialized = false; + } + + /** + * Instantly gets an asset already loaded from the cache. If the asset has not yet been loaded, + * it will return undefined. So it's on you! When in doubt just use `PIXI.Assets.load` instead. + * (remember, the loader will never load things more than once!) + * @param keys - The key or keys for the assets that you want to access + * @returns - The assets or hash of assets requested + */ + public get(keys: string | string[]): T | Record + { + if (typeof keys === 'string') + { + return Cache.get(keys); + } + + const assets: Record = {}; + + for (let i = 0; i < keys.length; i++) + { + assets[i] = Cache.get(keys[i]); + } + + return assets; + } + + /** + * helper function to map resolved assets back to loaded assets + * @param resolveResults - the resolve results from the resolver + * @param onProgress - the progress callback + */ + private async _mapLoadToResolve( + resolveResults: ResolveAsset | Record, + onProgress?: ProgressCallback + ): Promise> + { + const resolveArray = Object.values(resolveResults); + const resolveKeys = Object.keys(resolveResults); + + // pause background loader... + this._backgroundLoader.active = false; + + const loadedAssets = await this.loader.load(resolveArray, onProgress); + + // resume background loader... + this._backgroundLoader.active = true; + + // remap to the keys used.. + + const out: Record = {}; + + resolveArray.forEach((resolveResult, i) => + { + const asset = loadedAssets[resolveResult.src]; + + const keys = [resolveResult.src]; + + if (resolveResult.alias) + { + keys.push(...resolveResult.alias); + } + + out[resolveKeys[i]] = asset; + + Cache.set(keys, asset); + }); + + return out; + } + + /** + * Unload an asset or assets. As the Assets class is responsible for creating the assets via the `load` function + * this will make sure to destroy any assets and release them from memory. + * Once unloaded, you will need to load the asset again. + * + * Use this to help manage assets if you find that you have a large app and you want to free up memory. + * + * * it's up to you as the developer to make sure that textures are not actively being used when you unload them, + * Pixi won't break but you will end up with missing assets. Not a good look for the user! + * @example + * // load a URL: + * const myImageTexture = await PIXI.Assets.load('http://some.url.com/image.png'); // => returns a texture + * + * await PIXI.Assets.unload('http://some.url.com/image.png') + * + * myImageTexture <-- will now be destroyed. + * + * // unload multiple assets: + * const textures = await PIXI.Assets.unload(['thumper', 'chicko']); + * @param urls - the urls to unload + */ + public async unload( + urls: string | string[] | LoadAsset | LoadAsset[] + ): Promise + { + if (!this._initialized) + { + await this.init(); + } + + const urlArray = convertToList(urls) + .map((url) => + ((typeof url !== 'string') ? url.src : url)); + + // check cache first... + const resolveResults = this.resolver.resolve(urlArray); + + await this._unloadFromResolved(resolveResults); + } + + /** + * Bundles are a way to manage multiple assets at once. + * this will unload all files in a bundle. + * + * once a bundle has been unloaded, you need to load it again to have access to the assets. + * @example + * PIXI.Assets.addBundle({ + * 'thumper': 'http://some.url.com/thumper.png', + * }) + * + * const assets = await PIXI.Assets.loadBundle('thumper'); + * + * // now to unload.. + * + * await await PIXI.Assets.unloadBundle('thumper'); + * + * // all assets in the assets object will now have been destroyed and purged from the cache + * @param bundleIds - the bundle id or ids to unload + */ + public async unloadBundle(bundleIds: string | string[]): Promise + { + if (!this._initialized) + { + await this.init(); + } + + bundleIds = convertToList(bundleIds); + + const resolveResults = this.resolver.resolveBundle(bundleIds); + + const promises = Object.keys(resolveResults).map((bundleId) => + this._unloadFromResolved(resolveResults[bundleId])); + + await Promise.all(promises); + } + + private async _unloadFromResolved(resolveResult: ResolveAsset | Record) + { + const resolveArray = Object.values(resolveResult); + + resolveArray.forEach((resolveResult) => + { + Cache.remove(resolveResult.src); + }); + + await this.loader.unload(resolveArray); + } + + /** All the detection parsers currently added to the Assets class. */ + public get detections(): FormatDetectionParser[] + { + return this._detections; + } +} + +export const Assets = new AssetsClass(); + +// Handle registration of extensions +extensions + .handleByList(ExtensionType.LoadParser, Assets.loader.parsers) + .handleByList(ExtensionType.ResolveParser, Assets.resolver.parsers) + .handleByList(ExtensionType.CacheParser, Assets.cache.parsers) + .handleByList(ExtensionType.DetectionParser, Assets.detections); diff --git a/packages/assets/src/BackgroundLoader.ts b/packages/assets/src/BackgroundLoader.ts new file mode 100644 index 00000000000..8d348fdb645 --- /dev/null +++ b/packages/assets/src/BackgroundLoader.ts @@ -0,0 +1,107 @@ +import type { LoadAsset } from './loader'; +import type { Loader } from './loader/Loader'; + +/** + * Quietly Loads assets in the background. + * @memberof PIXI + */ +export class BackgroundLoader +{ + /** Whether or not the loader should continue loading. */ + private _isActive: boolean; + + /** Assets to load. */ + private readonly _assetList: LoadAsset[]; + + /** Whether or not the loader is loading. */ + private _isLoading: boolean; + + /** Number of assets to load at a time. */ + private readonly _maxConcurrent: number; + + /** Should the loader log to the console. */ + public verbose: boolean; + private readonly _loader: Loader; + + /** + * @param loader + * @param verbose - should the loader log to the console + */ + constructor(loader: Loader, verbose = false) + { + this._loader = loader; + this._assetList = []; + this._isLoading = false; + this._maxConcurrent = 1; + this.verbose = verbose; + } + + /** + * Adds an array of assets to load. + * @param assetUrls - assets to load + */ + public add(assetUrls: LoadAsset[]): void + { + assetUrls.forEach((a) => + { + this._assetList.push(a); + }); + + // eslint-disable-next-line no-console + if (this.verbose)console.log('[BackgroundLoader] assets: ', this._assetList); + + if (this._isActive && !this._isLoading) + { + this._next(); + } + } + + /** + * Loads the next set of assets. Will try to load as many assets as it can at the same time. + * + * The max assets it will try to load at one time will be 4. + */ + private async _next(): Promise + { + if (this._assetList.length && this._isActive) + { + this._isLoading = true; + + const toLoad = []; + + const toLoadAmount = Math.min(this._assetList.length, this._maxConcurrent); + + for (let i = 0; i < toLoadAmount; i++) + { + toLoad.push(this._assetList.pop()); + } + + await this._loader.load(toLoad); + + this._isLoading = false; + + this._next(); + } + } + + /** + * @returns whether the class is active + */ + get active(): boolean + { + return this._isActive; + } + + /** Activate/Deactivate the loading. If set to true then it will immediately continue to load the next asset. */ + set active(value: boolean) + { + if (this._isActive === value) return; + + this._isActive = value; + + if (value && !this._isLoading) + { + this._next(); + } + } +} diff --git a/packages/assets/src/cache/Cache.ts b/packages/assets/src/cache/Cache.ts new file mode 100644 index 00000000000..4a63033d561 --- /dev/null +++ b/packages/assets/src/cache/Cache.ts @@ -0,0 +1,180 @@ +import { BaseTexture, Texture } from '@pixi/core'; +import { convertToList } from '../utils'; +import type { CacheParser } from './CacheParser'; + +/** + * A single Cache for all assets. + * + * When assets are added to the cache via set they normally are added to the cache as key-value pairs. + * + * With this cache, you can add parsers that will take the object and convert it to a list of assets that can be cached. + * for example a cacheSprite Sheet parser will add all of the textures found within its sprite sheet directly to the cache. + * + * This gives devs the flexibility to cache any type of object however we want. + * + * It is not intended that this class is created by developers - it is part of the Asset package. + * This is the first major system of PixiJS' main Assets class. + * @memberof PIXI + * @class Cache + */ +class CacheClass +{ + private _parsers: CacheParser[] = []; + + private readonly _cache: Map = new Map(); + private readonly _cacheMap: Map = new Map(); + + /** Clear all entries. */ + public reset(): void + { + this._cacheMap.clear(); + this._cache.clear(); + } + + /** + * Check if the key exists + * @param key - The key to check + */ + public has(key: string): boolean + { + return this._cache.has(key); + } + + /** + * Fetch entry by key + * @param key - The key of the entry to get + */ + public get(key: string): T + { + const result = this._cache.get(key); + + if (!result) + { + // #if _DEBUG + console.warn(`[Assets] Asset id ${key} was not found in the Cache`); + // #endif + } + + return result as T; + } + + /** + * Set a value by key or keys name + * @param key - The key or keys to set + * @param value - The value to store in the cache or from which cacheable assets will be derived. + */ + public set(key: string | string[], value: unknown): void + { + const keys = convertToList(key); + + let cacheableAssets: Record; + + for (let i = 0; i < this.parsers.length; i++) + { + const parser = this.parsers[i]; + + if (parser.test(value)) + { + cacheableAssets = parser.getCacheableAssets(keys, value); + + break; + } + } + + if (!cacheableAssets) + { + cacheableAssets = {}; + + keys.forEach((key) => + { + cacheableAssets[key] = value; + }); + } + + const cacheKeys = Object.keys(cacheableAssets); + + const cachedAssets = { + cacheKeys, + keys + }; + + // this is so we can remove them later.. + keys.forEach((key) => + { + this._cacheMap.set(key, cachedAssets); + }); + + cacheKeys.forEach((key) => + { + if (this._cache.has(key) && this._cache.get(key) !== value) + { + // #if _DEBUG + console.warn('[Cache] already has key:', key); + // #endif + } + + this._cache.set(key, cacheableAssets[key]); + }); + + // temporary to keep compatible with existing texture caching.. until we remove them! + if (value instanceof Texture) + { + const texture: Texture = value; + + keys.forEach((key) => + { + if (texture.baseTexture !== Texture.EMPTY.baseTexture) + { + BaseTexture.addToCache(texture.baseTexture, key); + } + + Texture.addToCache(texture, key); + }); + } + } + + /** + * Remove entry by key + * + * This function will also remove any associated alias from the cache also. + * @param key - The key of the entry to remove + */ + public remove(key: string): void + { + this._cacheMap.get(key); + + if (!this._cacheMap.has(key)) + { + // #if _DEBUG + console.warn(`[Assets] Asset id ${key} was not found in the Cache`); + // #endif + + return; + } + + const cacheMap = this._cacheMap.get(key); + + const cacheKeys = cacheMap.cacheKeys; + + cacheKeys.forEach((key) => + { + this._cache.delete(key); + }); + + cacheMap.keys.forEach((key: string) => + { + this._cacheMap.delete(key); + }); + } + + /** All loader parsers registered */ + public get parsers(): CacheParser[] + { + return this._parsers; + } +} + +export const Cache = new CacheClass(); diff --git a/packages/assets/src/cache/CacheParser.ts b/packages/assets/src/cache/CacheParser.ts new file mode 100644 index 00000000000..7a8d868cacb --- /dev/null +++ b/packages/assets/src/cache/CacheParser.ts @@ -0,0 +1,35 @@ +import type { ExtensionMetadata } from '@pixi/core'; + +/** + * For every asset that is cached, it will call the parsers test function + * the flow is as follows: + * + * 1. `cacheParser.test()`: Test the asset. + * 2. `cacheParser.getCacheableAssets()`: If the test passes call the getCacheableAssets function with the asset + * + * Useful if you want to add more than just a raw asset to the cache + * (for example a spritesheet will want to make all its sub textures easily accessible in the cache) + */ +export interface CacheParser +{ + extension?: ExtensionMetadata; + + /** A config to adjust the parser */ + config?: Record + + /** + * Gets called by the cache when a dev caches an asset + * @param asset - the asset to test + */ + test: (asset: T) => boolean; + + /** + * If the test passes, this function is called to get the cacheable assets + * an example may be that a spritesheet object will return all the sub textures it has so they can + * be cached. + * @param keys - The keys to cache the assets under + * @param asset - The asset to get the cacheable assets from + * @returns A key-value pair of cacheable assets + */ + getCacheableAssets: (keys: string[], asset: T) => Record; +} diff --git a/packages/assets/src/cache/index.ts b/packages/assets/src/cache/index.ts new file mode 100644 index 00000000000..51b4329803c --- /dev/null +++ b/packages/assets/src/cache/index.ts @@ -0,0 +1,3 @@ +export * from './Cache'; +export * from './parsers'; +export * from './CacheParser'; diff --git a/packages/assets/src/cache/parsers/cacheTextureArray.ts b/packages/assets/src/cache/parsers/cacheTextureArray.ts new file mode 100644 index 00000000000..3d98a0f48d1 --- /dev/null +++ b/packages/assets/src/cache/parsers/cacheTextureArray.ts @@ -0,0 +1,25 @@ +import { extensions, ExtensionType, Texture } from '@pixi/core'; +import type { CacheParser } from '../CacheParser'; + +export const cacheTextureArray: CacheParser = { + extension: ExtensionType.CacheParser, + + test: (asset: any[]) => Array.isArray(asset) && asset.every((t) => t instanceof Texture), + + getCacheableAssets: (keys: string[], asset: Texture[]) => + { + const out: Record = {}; + + keys.forEach((key: string) => + { + asset.forEach((item: Texture, i: number) => + { + out[key + (i === 0 ? '' : i + 1)] = item; + }); + }); + + return out; + } +}; + +extensions.add(cacheTextureArray); diff --git a/packages/assets/src/cache/parsers/index.ts b/packages/assets/src/cache/parsers/index.ts new file mode 100644 index 00000000000..a5398b85a93 --- /dev/null +++ b/packages/assets/src/cache/parsers/index.ts @@ -0,0 +1,2 @@ +export * from './cacheTextureArray'; + diff --git a/packages/assets/src/detections/index.ts b/packages/assets/src/detections/index.ts new file mode 100644 index 00000000000..40fb7a9f1ff --- /dev/null +++ b/packages/assets/src/detections/index.ts @@ -0,0 +1,12 @@ +import type { ExtensionMetadata } from '@pixi/core'; + +export interface FormatDetectionParser +{ + extension?: ExtensionMetadata; + test: () => Promise, + add: (formats: string[]) => Promise, + remove: (formats: string[]) => Promise, +} + +export * from './parsers'; +export * from './utils'; diff --git a/packages/assets/src/detections/parsers/detectAvif.ts b/packages/assets/src/detections/parsers/detectAvif.ts new file mode 100644 index 00000000000..40e5ee15168 --- /dev/null +++ b/packages/assets/src/detections/parsers/detectAvif.ts @@ -0,0 +1,24 @@ +import { settings, extensions, ExtensionType } from '@pixi/core'; +import type { FormatDetectionParser } from '..'; +import { addFormats, removeFormats } from '../utils/detectUtils'; + +export const detectAvif: FormatDetectionParser = { + extension: { + type: ExtensionType.DetectionParser, + priority: 1, + }, + test: async (): Promise => + { + if (!globalThis.createImageBitmap) return false; + + // eslint-disable-next-line max-len + const avifData = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A='; + const blob = await settings.ADAPTER.fetch(avifData).then((r) => r.blob()); + + return createImageBitmap(blob).then(() => true, () => false); + }, + add: addFormats('avif'), + remove: removeFormats('avif') +}; + +extensions.add(detectAvif); diff --git a/packages/assets/src/detections/parsers/detectDefaults.ts b/packages/assets/src/detections/parsers/detectDefaults.ts new file mode 100644 index 00000000000..32b0b751dd0 --- /dev/null +++ b/packages/assets/src/detections/parsers/detectDefaults.ts @@ -0,0 +1,15 @@ +import { extensions, ExtensionType } from '@pixi/core'; +import type { FormatDetectionParser } from '..'; +import { addFormats, removeFormats } from '../utils/detectUtils'; + +export const detectDefaults = { + extension: { + type: ExtensionType.DetectionParser, + priority: -1, + }, + test: (): Promise => Promise.resolve(true), + add: addFormats('png', 'jpg', 'jpeg'), + remove: removeFormats('png', 'jpg', 'jpeg') +} as FormatDetectionParser; + +extensions.add(detectDefaults); diff --git a/packages/assets/src/detections/parsers/detectWebp.ts b/packages/assets/src/detections/parsers/detectWebp.ts new file mode 100644 index 00000000000..03f15ddcc85 --- /dev/null +++ b/packages/assets/src/detections/parsers/detectWebp.ts @@ -0,0 +1,23 @@ +import { settings, extensions, ExtensionType } from '@pixi/core'; +import type { FormatDetectionParser } from '..'; +import { addFormats, removeFormats } from '../utils/detectUtils'; + +export const detectWebp = { + extension: { + type: ExtensionType.DetectionParser, + priority: 0, + }, + test: async (): Promise => + { + if (!globalThis.createImageBitmap) return false; + + const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA='; + const blob = await settings.ADAPTER.fetch(webpData).then((r) => r.blob()); + + return createImageBitmap(blob).then(() => true, () => false); + }, + add: addFormats('webp'), + remove: removeFormats('webp') +} as FormatDetectionParser; + +extensions.add(detectWebp); diff --git a/packages/assets/src/detections/parsers/index.ts b/packages/assets/src/detections/parsers/index.ts new file mode 100644 index 00000000000..5282a8a70da --- /dev/null +++ b/packages/assets/src/detections/parsers/index.ts @@ -0,0 +1,3 @@ +export * from './detectAvif'; +export * from './detectWebp'; +export * from './detectDefaults'; diff --git a/packages/assets/src/detections/utils/detectUtils.ts b/packages/assets/src/detections/utils/detectUtils.ts new file mode 100644 index 00000000000..6d48cc1f262 --- /dev/null +++ b/packages/assets/src/detections/utils/detectUtils.ts @@ -0,0 +1,26 @@ +export function addFormats(...format: string[]): (formats: string[]) => Promise +{ + return async (formats: string[]) => + { + formats.push(...format); + + return formats; + }; +} +export function removeFormats(...format: string[]): (formats: string[]) => Promise +{ + return async (formats: string[]) => + { + for (const f of format) + { + const index = formats.indexOf(f); + + if (index !== -1) + { + formats.splice(index, 1); + } + } + + return formats; + }; +} diff --git a/packages/assets/src/detections/utils/index.ts b/packages/assets/src/detections/utils/index.ts new file mode 100644 index 00000000000..f1d13fdd373 --- /dev/null +++ b/packages/assets/src/detections/utils/index.ts @@ -0,0 +1 @@ +export * from './detectUtils'; diff --git a/packages/assets/src/index.ts b/packages/assets/src/index.ts new file mode 100644 index 00000000000..e7a1078ce43 --- /dev/null +++ b/packages/assets/src/index.ts @@ -0,0 +1,7 @@ +export * from './Assets'; +export * from './utils'; +export * from './cache'; +export * from './loader'; +export * from './resolver'; +export * from './detections'; + diff --git a/packages/assets/src/loader/Loader.ts b/packages/assets/src/loader/Loader.ts new file mode 100644 index 00000000000..36f56ddbe89 --- /dev/null +++ b/packages/assets/src/loader/Loader.ts @@ -0,0 +1,202 @@ +import { utils } from '@pixi/core'; +import { convertToList, isSingleItem } from '../utils'; +import type { LoaderParser } from './parsers/LoaderParser'; +import type { PromiseAndParser, LoadAsset } from './types'; + +/** + * The Loader is responsible for loading all assets, such as images, spritesheets, audio files, etc. + * It does not do anything clever with URLs - it just loads stuff! + * Behind the scenes all things are cached using promises. This means it's impossible to load an asset more than once. + * Through the use of LoaderParsers, the loader can understand how to load any kind of file! + * + * It is not intended that this class is created by developers - its part of the Asset class + * This is the second major system of PixiJS' main Assets class + * @memberof PIXI + * @class AssetLoader + */ +export class Loader +{ + private _parsers: LoaderParser[] = []; + + /** Cache loading promises that ae currently active */ + public promiseCache: Record = {}; + + /** function used for testing */ + public reset(): void + { + this.promiseCache = {}; + } + + /** + * Used internally to generate a promise for the asset to be loaded. + * @param url - The URL to be loaded + * @param data - any custom additional information relevant to the asset being loaded + * @returns - a promise that will resolve to an Asset for example a Texture of a JSON object + */ + private _getLoadPromiseAndParser(url: string, data?: LoadAsset): PromiseAndParser + { + const result: PromiseAndParser = { + promise: null, + parser: null + }; + + result.promise = (async () => + { + let asset = null; + + for (let i = 0; i < this.parsers.length; i++) + { + const parser = this.parsers[i]; + + if (parser.load && parser.test?.(url, data, this)) + { + asset = await parser.load(url, data, this); + result.parser = parser; + + break; + } + } + + if (!result.parser) + { + // #if _DEBUG + // eslint-disable-next-line max-len + console.warn(`[Assets] ${url} could not be loaded as we don't know how to parse it, ensure the correct parser has being added`); + // #endif + + return null; + } + + for (let i = 0; i < this.parsers.length; i++) + { + const parser = this.parsers[i]; + + if (parser.parse) + { + if (parser.parse && await parser.testParse?.(asset, data, this)) + { + // transform the asset.. + asset = await parser.parse(asset, data, this) || asset; + + result.parser = parser; + } + } + } + + return asset; + })(); + + return result; + } + + /** + * Loads an asset(s) using the parsers added to the Loader. + * @example + * // single asset: + * const asset = await Loader.load('cool.png'); + * console.log(asset); + * @example + * // multiple assets: + * const assets = await Loader.load(['cool.png', 'cooler.png']); + * console.log(assets); + * @param assetsToLoadIn - urls that you want to load, or a single one! + * @param onProgress - a function that gets called when the progress changes + */ + public async load( + assetsToLoadIn: string | string[] | LoadAsset | LoadAsset[], + onProgress?: (progress: number) => void, + ): Promise<{[key: string]: any} | any> + { + let count = 0; + + const assets: Record> = {}; + + const singleAsset = isSingleItem(assetsToLoadIn); + + const assetsToLoad = convertToList(assetsToLoadIn, (item) => ({ + src: item, + })); + + const total = assetsToLoad.length; + + const promises: Promise[] = assetsToLoad.map(async (asset: LoadAsset) => + { + const url = utils.path.toAbsolute(asset.src); + + if (!assets[asset.src]) + { + try + { + if (!this.promiseCache[url]) + { + this.promiseCache[url] = this._getLoadPromiseAndParser(url, asset); + } + + assets[asset.src] = await this.promiseCache[url].promise; + + // Only progress if nothing goes wrong + if (onProgress) onProgress(++count / total); + } + catch (e) + { + // Delete eventually registered file and promises from internal cache + // so they can be eligible for another loading attempt + delete this.promiseCache[url]; + delete assets[asset.src]; + + // Stop further execution + throw new Error(`[Loader.load] Failed to load ${url}.\n${e}`); + } + } + }); + + await Promise.all(promises); + + return singleAsset ? assets[assetsToLoad[0].src] : assets; + } + + /** + * Unloads an asset(s). Any unloaded assets will be destroyed, freeing up memory for your app. + * The parser that created the asset, will be the one that unloads it. + * @example + * // single asset: + * const asset = await Loader.load('cool.png'); + * + * await Loader.unload('cool.png'); + * + * console.log(asset.destroyed); // true + * @param assetsToUnloadIn - urls that you want to unload, or a single one! + */ + public async unload( + assetsToUnloadIn: string | string[] | LoadAsset | LoadAsset[], + ): Promise + { + const assetsToUnload = convertToList(assetsToUnloadIn, (item) => ({ + src: item, + })); + + const promises: Promise[] = assetsToUnload.map(async (asset: LoadAsset) => + { + const url = utils.path.toAbsolute(asset.src); + + const loadPromise = this.promiseCache[url]; + + if (loadPromise) + { + const loadedAsset = await loadPromise.promise; + + loadPromise.parser?.unload?.(loadedAsset, asset, this); + + delete this.promiseCache[url]; + } + }); + + await Promise.all(promises); + } + + /** All loader parsers registered */ + public get parsers(): LoaderParser[] + { + return this._parsers; + } +} diff --git a/packages/assets/src/loader/index.ts b/packages/assets/src/loader/index.ts new file mode 100644 index 00000000000..75563d3758f --- /dev/null +++ b/packages/assets/src/loader/index.ts @@ -0,0 +1,3 @@ +export * from './types'; +export type { Loader } from './Loader'; +export * from './parsers'; diff --git a/packages/assets/src/loader/parsers/LoaderParser.ts b/packages/assets/src/loader/parsers/LoaderParser.ts new file mode 100644 index 00000000000..d05fbb80a6a --- /dev/null +++ b/packages/assets/src/loader/parsers/LoaderParser.ts @@ -0,0 +1,85 @@ +import type { ExtensionMetadata } from '@pixi/core'; +import type { Loader } from '../Loader'; +import type { LoadAsset } from '../types'; + +/** + * The extension priority for loader parsers. + * Helpful when managing multiple parsers that share the same extension + * test. The higher priority parsers will be checked first. + */ +export enum LoaderParserPriority +// eslint-disable-next-line @typescript-eslint/indent +{ + /** Generic parsers: txt, json, webfonts */ + Low = 0, + /** PixiJS assets with generic extensions: spritesheets, bitmapfonts */ + Normal = 1, + /** Specific texture types: svg, png, ktx, dds, basis */ + High = 2, +} + +/** + * All functions are optional here. The flow: + * + * for every asset, + * + * 1. `parser.test()`: Test the asset url. + * 2. `parser.load()`: If test passes call the load function with the url + * 3. `parser.testParse()`: Test to see if the asset should be parsed by the plugin + * 4. `parse.parse()`: If test is parsed, then run the parse function on the asset. + * + * some plugins may only be used for parsing, + * some only for loading + * and some for both! + */ +export interface LoaderParser +{ + extension?: ExtensionMetadata; + + /** A config to adjust the parser */ + config?: Record + /** + * each URL to load will be tested here, + * if the test is passed the assets are loaded using the load function below. + * Good place to test for things like file extensions! + * @param url - The URL to test + * @param loadAsset - Any custom additional information relevant to the asset being loaded + * @param loader - The loader instance + */ + test?: (url: string, loadAsset?: LoadAsset, loader?: Loader) => boolean; + + /** + * This is the promise that loads the URL provided + * resolves with a loaded asset if returned by the parser. + * @param url - The URL to load + * @param loadAsset - Any custom additional information relevant to the asset being loaded + * @param loader - The loader instance + */ + load?: (url: string, loadAsset?: LoadAsset, loader?: Loader) => Promise; + + /** + * This function is used to test if the parse function should be run on the asset + * If this returns true then parse is called with the asset + * @param asset - The loaded asset data + * @param loadAsset - Any custom additional information relevant to the asset being loaded + * @param loader - The loader instance + */ + testParse?: (asset: ASSET, loadAsset?: LoadAsset, loader?: Loader) => Promise; + + /** + * Gets called on the asset it testParse passes. Useful to convert a raw asset into something more useful than + * @param asset - The loaded asset data + * @param loadAsset - Any custom additional information relevant to the asset being loaded + * @param loader - The loader instance + */ + parse?: (asset: ASSET, loadAsset?: LoadAsset, loader?: Loader) => Promise; + + /** + * If an asset is parsed using this parser, the unload function will be called when the user requests an asset + * to be unloaded. This is useful for things like sounds or textures that can be unloaded from memory + * @param asset - The asset to unload/destroy + * @param loadAsset - Any custom additional information relevant to the asset being loaded + * @param loader - The loader instance + */ + unload?: (asset: ASSET, loadAsset?: LoadAsset, loader?: Loader) => void; +} diff --git a/packages/assets/src/loader/parsers/WorkerManager.ts b/packages/assets/src/loader/parsers/WorkerManager.ts new file mode 100644 index 00000000000..ba3046d5d64 --- /dev/null +++ b/packages/assets/src/loader/parsers/WorkerManager.ts @@ -0,0 +1,155 @@ +let UUID = 0; +let MAX_WORKERS: number; + +const workerCode = { + id: 'loadImageBitmap', + code: ` + self.onmessage = function(event) { + + async function loadImageBitmap(url) + { + const response = await fetch(url); + const imageBlob = await response.blob(); + const imageBitmap = await createImageBitmap(imageBlob); + return imageBitmap; + } + + loadImageBitmap(event.data.data[0]).then(imageBitmap => { + self.postMessage({ + data: imageBitmap, + uuid: event.data.uuid, + id: event.data.id, + }, [imageBitmap]); + }).catch(error => { + self.postMessage({ + data: null, + uuid: event.data.uuid, + id: event.data.id, + }); + }); + }`, +}; + +let workerURL: string; + +class WorkerManagerClass +{ + public worker: Worker; + private resolveHash: {[key: string]: (...param: any[]) => void}; + private readonly workerPool: Worker[]; + private readonly queue: { id: string; arguments: any[]; resolve: (...param: any[]) => void }[]; + private _initialized = false; + private _createdWorkers = 0; + + constructor() + { + this.workerPool = []; + this.queue = []; + + this.resolveHash = {}; + } + + public loadImageBitmap(src: string): Promise + { + return this._run('loadImageBitmap', [src]) as Promise; + } + + private async _initWorkers() + { + if (this._initialized) return; + + this._initialized = true; + } + + private getWorker(): Worker + { + if (MAX_WORKERS === undefined) + { + MAX_WORKERS = navigator.hardwareConcurrency || 4; + } + let worker = this.workerPool.pop(); + + if (!worker && this._createdWorkers < MAX_WORKERS) + { + if (!workerURL) + { + workerURL = URL.createObjectURL(new Blob([workerCode.code], { type: 'application/javascript' })); + } + + // only create as many as MAX_WORKERS allows.. + this._createdWorkers++; + worker = new Worker(workerURL); + + worker.addEventListener('message', (event: MessageEvent) => + { + this.complete(event.data); + + this.returnWorker(event.target as Worker); + this.next(); + }); + } + + return worker; + } + + private returnWorker(worker: Worker) + { + this.workerPool.push(worker); + } + + private complete(data: any): void + { + const result = data.data; + + this.resolveHash[data.uuid](result); + + this.resolveHash[data.uuid] = null; + } + + private _run(id: string, args: any[]): Promise + { + this._initWorkers(); + // push into the queue... + + const promise = new Promise((resolve) => + { + this.queue.push({ id, arguments: args, resolve }); + }); + + this.next(); + + return promise; + } + + private next(): void + { + // nothing to do + if (!this.queue.length) return; + + const worker = this.getWorker(); + + // no workers available... + if (!worker) + { + return; + } + + const toDo = this.queue.pop(); + + const id = toDo.id; + + this.resolveHash[UUID] = toDo.resolve; + + worker.postMessage({ + data: toDo.arguments, + uuid: UUID++, + id, + }); + } +} + +const WorkerManager = new WorkerManagerClass(); + +export { + WorkerManager, +}; diff --git a/packages/assets/src/loader/parsers/index.ts b/packages/assets/src/loader/parsers/index.ts new file mode 100644 index 00000000000..42b4ff5313d --- /dev/null +++ b/packages/assets/src/loader/parsers/index.ts @@ -0,0 +1,6 @@ +export * from './LoaderParser'; +export * from './loadJson'; +export * from './loadTxt'; +export * from './loadWebFont'; +export * from './textures'; + diff --git a/packages/assets/src/loader/parsers/loadJson.ts b/packages/assets/src/loader/parsers/loadJson.ts new file mode 100644 index 00000000000..378a9451fcb --- /dev/null +++ b/packages/assets/src/loader/parsers/loadJson.ts @@ -0,0 +1,28 @@ +import { settings, utils, extensions, ExtensionType } from '@pixi/core'; +import { LoaderParserPriority } from './LoaderParser'; + +import type { LoaderParser } from './LoaderParser'; + +/** simple loader plugin for loading json data */ +export const loadJson = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.Low, + }, + + test(url: string): boolean + { + return (utils.path.extname(url).includes('.json')); + }, + + async load(url: string): Promise + { + const response = await settings.ADAPTER.fetch(url); + + const json = await response.json(); + + return json as T; + }, +} as LoaderParser; + +extensions.add(loadJson); diff --git a/packages/assets/src/loader/parsers/loadTxt.ts b/packages/assets/src/loader/parsers/loadTxt.ts new file mode 100644 index 00000000000..9a6fb7e6549 --- /dev/null +++ b/packages/assets/src/loader/parsers/loadTxt.ts @@ -0,0 +1,28 @@ +import { settings, utils, extensions, ExtensionType } from '@pixi/core'; +import { LoaderParserPriority } from './LoaderParser'; + +import type { LoaderParser } from './LoaderParser'; + +/** Simple loader plugin for loading text data */ +export const loadTxt = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.Low, + }, + + test(url: string): boolean + { + return (utils.path.extname(url).includes('.txt')); + }, + + async load(url: string): Promise + { + const response = await settings.ADAPTER.fetch(url); + + const txt = await response.text(); + + return txt; + }, +} as LoaderParser; + +extensions.add(loadTxt); diff --git a/packages/assets/src/loader/parsers/loadWebFont.ts b/packages/assets/src/loader/parsers/loadWebFont.ts new file mode 100644 index 00000000000..f23041da406 --- /dev/null +++ b/packages/assets/src/loader/parsers/loadWebFont.ts @@ -0,0 +1,107 @@ +import { extensions, ExtensionType, utils } from '@pixi/core'; +import type { LoadAsset } from '../types'; +import type { LoaderParser } from './LoaderParser'; +import { LoaderParserPriority } from './LoaderParser'; + +const validWeights = ['normal', 'bold', + '100', '200', '300', '400', '500', '600', '700', '800', '900', +]; +const validFonts = ['woff', 'woff2', 'ttf', 'otf']; + +export type LoadFontData = { + family: string; + display: string; + featureSettings: string; + stretch: string; + style: string; + unicodeRange: string; + variant: string; + weights: string[]; +}; + +/** + * Return font face name from a file name + * Ex.: 'fonts/tital-one.woff' turns into 'Titan One' + * @param url - File url + */ +export function getFontFamilyName(url: string): string +{ + const ext = utils.path.extname(url); + const name = utils.path.basename(url, ext); + + // Replace dashes by white spaces + const nameWithSpaces = name.replace(/(-|_)/g, ' '); + + // Upper case first character of each word + const nameTitleCase = nameWithSpaces.toLowerCase() + .split(' ') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + return nameTitleCase; +} + +/** Web font loader plugin */ +export const loadWebFont = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.Low, + }, + + test(url: string): boolean + { + const tempURL = url.split('?')[0]; + const extension = tempURL.split('.').pop(); + + return validFonts.includes(extension); + }, + + async load(url: string, options?: LoadAsset): Promise + { + // Prevent loading font if navigator is not online + if (!window.navigator.onLine) + { + throw new Error('[loadWebFont] Cannot load font - navigator is offline'); + } + + if ('FontFace' in window) + { + const fontFaces: FontFace[] = []; + const name = options.data?.family ?? getFontFamilyName(url); + const weights = options.data?.weights?.filter((weight) => validWeights.includes(weight)) ?? ['normal']; + const data = options.data ?? {}; + + for (let i = 0; i < weights.length; i++) + { + const weight = weights[i]; + + const font = new FontFace(name, `url(${url})`, { + ...data, + weight, + }); + + await font.load(); + + document.fonts.add(font); + + fontFaces.push(font); + } + + return fontFaces.length === 1 ? fontFaces[0] : fontFaces; + } + + // #if _DEBUG + console.warn('[loadWebFont] FontFace API is not supported. Skipping loading font'); + // #endif + + return null; + }, + + unload(font: FontFace | FontFace[]): void + { + (Array.isArray(font) ? font : [font]) + .forEach((t) => document.fonts.delete(t)); + } +} as LoaderParser; + +extensions.add(loadWebFont); diff --git a/packages/assets/src/loader/parsers/textures/index.ts b/packages/assets/src/loader/parsers/textures/index.ts new file mode 100644 index 00000000000..f606200bcdf --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/index.ts @@ -0,0 +1,4 @@ +export * from './loadSVG'; +export * from './loadTexture'; +export * from './utils'; + diff --git a/packages/assets/src/loader/parsers/textures/loadSVG.ts b/packages/assets/src/loader/parsers/textures/loadSVG.ts new file mode 100644 index 00000000000..ade9caf2adc --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/loadSVG.ts @@ -0,0 +1,58 @@ +import { settings, utils, BaseTexture, ExtensionType, SVGResource } from '@pixi/core'; +import { LoaderParserPriority } from '../LoaderParser'; +import { loadTextures } from './loadTexture'; +import { createTexture } from './utils/createTexture'; + +import type { IBaseTextureOptions, Texture } from '@pixi/core'; +import type { Loader } from '../../Loader'; +import type { LoadAsset } from '../../types'; +import type { LoaderParser } from '../LoaderParser'; + +/** Loads SVG's into Textures */ +export const loadSVG = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.High, + }, + + test(url: string): boolean + { + return (utils.path.extname(url).includes('.svg')); + }, + + async testParse(data: string): Promise + { + return SVGResource.test(data); + }, + + async parse(asset: string, data: LoadAsset, loader: Loader): Promise + { + const src = new SVGResource(asset, data?.data?.resourceOptions); + + const base = new BaseTexture(src, { + resolution: utils.getResolutionOfUrl(asset), + ...data?.data, + }); + + base.resource.src = asset; + + const texture = createTexture(base, loader, asset); + + if (!data?.data?.resourceOptions?.autoLoad) + { + await src.load(); + } + + return texture; + }, + + async load(url: string, _options: LoadAsset): Promise + { + const response = await settings.ADAPTER.fetch(url); + + return response.text(); + }, + + unload: loadTextures.unload, + +} as LoaderParser; diff --git a/packages/assets/src/loader/parsers/textures/loadTexture.ts b/packages/assets/src/loader/parsers/textures/loadTexture.ts new file mode 100644 index 00000000000..3eab2f3633a --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/loadTexture.ts @@ -0,0 +1,107 @@ +import { BaseTexture, extensions, ExtensionType, settings, utils } from '@pixi/core'; +import type { Loader } from '../../Loader'; +import type { LoadAsset } from '../../types'; +import { LoaderParserPriority } from '../LoaderParser'; +import { WorkerManager } from '../WorkerManager'; +import { checkExtension } from './utils/checkExtension'; +import { createTexture } from './utils/createTexture'; + +import type { IBaseTextureOptions, Texture } from '@pixi/core'; +import type { LoaderParser } from '../LoaderParser'; + +const validImages = ['.jpg', '.png', '.jpeg', '.avif', '.webp']; + +/** + * Returns a promise that resolves an ImageBitmaps. + * This function is designed to be used by a worker. + * Part of WorkerManager! + * @param url - The image to load an image bitmap for + */ +export async function loadImageBitmap(url: string): Promise +{ + const response = await settings.ADAPTER.fetch(url); + const imageBlob = await response.blob(); + const imageBitmap = await createImageBitmap(imageBlob); + + return imageBitmap; +} + +/** + * Loads our textures! + * this makes use of imageBitmaps where available. + * We load the ImageBitmap on a different thread using the WorkerManager + * We can then use the ImageBitmap as a source for a Pixi Texture + */ +export const loadTextures = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.High, + }, + + config: { + preferWorkers: true, + }, + + test(url: string): boolean + { + let isValidBase64Suffix = false; + + for (let i = 0; i < validImages.length; i++) + { + if (url.indexOf(`data:image/${validImages[i].slice(1)}`) === 0) + { + isValidBase64Suffix = true; + break; + } + } + + return isValidBase64Suffix || checkExtension(url, validImages); + }, + + async load(url: string, asset: LoadAsset, loader: Loader): Promise + { + let src: any = null; + + if (window.createImageBitmap) + { + src = this.config.preferWorkers ? await WorkerManager.loadImageBitmap(url) : await loadImageBitmap(url); + } + else + { + src = await new Promise((resolve) => + { + src = new Image(); + src.crossOrigin = 'anonymous'; + + src.src = url; + if (src.complete) + { + resolve(src); + } + else + { + src.onload = (): void => + { + resolve(src); + }; + } + }); + } + + const base = new BaseTexture(src, { + resolution: utils.getResolutionOfUrl(url), + ...asset.data, + }); + + base.resource.src = url; + + return createTexture(base, loader, url); + }, + + unload(texture: Texture): void + { + texture.destroy(true); + } +} as LoaderParser; + +extensions.add(loadTextures); diff --git a/packages/assets/src/loader/parsers/textures/utils/checkExtension.ts b/packages/assets/src/loader/parsers/textures/utils/checkExtension.ts new file mode 100644 index 00000000000..1e5c63f1ee0 --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/utils/checkExtension.ts @@ -0,0 +1,14 @@ +import { utils } from '@pixi/core'; + +export function checkExtension(url: string, extension: string | string[]): boolean +{ + const tempURL = url.split('?')[0]; + const ext = utils.path.extname(tempURL).toLowerCase(); + + if (Array.isArray(extension)) + { + return extension.includes(ext.toLowerCase()); + } + + return ext.toLowerCase() === extension; +} diff --git a/packages/assets/src/loader/parsers/textures/utils/createTexture.ts b/packages/assets/src/loader/parsers/textures/utils/createTexture.ts new file mode 100644 index 00000000000..7e150dc706d --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/utils/createTexture.ts @@ -0,0 +1,16 @@ +import type { BaseTexture } from '@pixi/core'; +import { Texture } from '@pixi/core'; +import type { Loader } from '../../../Loader'; + +export function createTexture(base: BaseTexture, loader: Loader, url: string) +{ + const texture = new Texture(base); + + // make sure to nuke the promise if a texture is destroyed.. + texture.baseTexture.on('dispose', () => + { + delete loader.promiseCache[url]; + }); + + return texture; +} diff --git a/packages/assets/src/loader/parsers/textures/utils/index.ts b/packages/assets/src/loader/parsers/textures/utils/index.ts new file mode 100644 index 00000000000..330853232e4 --- /dev/null +++ b/packages/assets/src/loader/parsers/textures/utils/index.ts @@ -0,0 +1,2 @@ +export * from './checkExtension'; +export * from './createTexture'; diff --git a/packages/assets/src/loader/types.ts b/packages/assets/src/loader/types.ts new file mode 100644 index 00000000000..f9d1166aa1d --- /dev/null +++ b/packages/assets/src/loader/types.ts @@ -0,0 +1,13 @@ +import type { LoaderParser } from './parsers'; + +export interface LoadAsset +{ + src: string; + data?: T; +} + +export interface PromiseAndParser +{ + promise: Promise + parser: LoaderParser +} diff --git a/packages/assets/src/resolver/Resolver.ts b/packages/assets/src/resolver/Resolver.ts new file mode 100644 index 00000000000..93b3f689435 --- /dev/null +++ b/packages/assets/src/resolver/Resolver.ts @@ -0,0 +1,544 @@ +import { utils } from '@pixi/core'; +import { convertToList } from '../utils/convertToList'; +import { createStringVariations } from '../utils/createStringVariations'; +import { isSingleItem } from '../utils/isSingleItem'; +import type { ResolveAsset, PreferOrder, ResolveURLParser, ResolverManifest, ResolverBundle } from './types'; + +/** + * A class that is responsible for resolving mapping asset URLs to keys. + * At its most basic it can be used for Aliases: + * + * ``` + * resolver.add('foo', 'bar'); + * resolver.resolveUrl('foo') // => 'bar' + * ``` + * + * It can also be used to resolve the most appropriate asset for a given URL: + * + * ``` + * resolver.prefer({ + * params:{ + * format:'webp', + * resolution: 2, + * } + * }) + * + * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']); + * + * resolver.resolveUrl('foo') // => 'bar@2x.webp' + * ``` + * Other features include: + * - Ability to process a manifest file to get the correct understanding of how to resolve all assets + * - Ability to add custom parsers for specific file types + * - Ability to add custom prefer rules + * + * This class only cares about the URL, not the loading of the asset itself. + * + * It is not intended that this class is created by developers - its part of the Asset class + * This is the third major system of PixiJS' main Assets class + * @memberof PIXI + */ +export class Resolver +{ + private _assetMap: Record = {}; + private _preferredOrder: PreferOrder[] = []; + private _parsers: ResolveURLParser[] = []; + + private _resolverHash: Record = {}; + private _rootPath: string; + private _basePath: string; + private _manifest: ResolverManifest; + private _bundles: Record = {}; + + /** + * Let the resolver know which assets you prefer to use when resolving assets. + * Multiple prefer user defined rules can be added. + * @example + * resolver.prefer({ + * // first look for something with the correct format, and then then correct resolution + * priority: ['format', 'resolution'], + * params:{ + * format:'webp', // prefer webp images + * resolution: 2, // prefer a resolution of 2 + * } + * }) + * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']); + * resolver.resolveUrl('foo') // => 'bar@2x.webp' + * @param preferOrders - the prefer options + */ + public prefer(...preferOrders: PreferOrder[]): void + { + preferOrders.forEach((prefer) => + { + this._preferredOrder.push(prefer); + + if (!prefer.priority) + { + // generate the priority based on the order of the object + prefer.priority = Object.keys(prefer.params); + } + }); + + this._resolverHash = {}; + } + + /** + * Set the base path to prepend to all urls when resolving + * @example + * resolver.basePath = 'https://home.com/'; + * resolver.add('foo', 'bar.ong'); + * resolver.resolveUrl('foo', 'bar.png'); // => 'https://home.com/bar.png' + * @param basePath - the base path to use + */ + public set basePath(basePath: string) + { + this._basePath = basePath; + } + + public get basePath(): string + { + return this._basePath; + } + + /** + * Set the root path for root-relative URLs. By default the `basePath`'s root is used. If no `basePath` is set, then the + * default value for browsers is `window.location.origin` + * @example + * // Application hosted on https://home.com/some-path/index.html + * resolver.basePath = 'https://home.com/some-path/'; + * resolver.rootPath = 'https://home.com/'; + * resolver.add('foo', '/bar.png'); + * resolver.resolveUrl('foo', '/bar.png'); // => 'https://home.com/bar.png' + * @param rootPath - the root path to use + */ + public set rootPath(rootPath: string) + { + this._rootPath = rootPath; + } + + public get rootPath(): string + { + return this._rootPath; + } + + /** + * All the active URL parsers that help the parser to extract information and create + * an asset object-based on parsing the URL itself. + * + * Can be added using the extensions API + * @example + * resolver.add('foo', [ + * { + * resolution:2, + * format:'png' + * src: 'image@2x.png' + * }, + * { + * resolution:1, + * format:'png' + * src: 'image.png' + * } + * ]); + * + * // with a url parser the information such as resolution and file format could extracted from the url itself: + * extensions.add({ + * extension: ExtensionType.ResolveParser, + * test: loadTextures.test, // test if url ends in an image + * parse: (value: string) => + * ({ + * resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + * format: value.split('.').pop(), + * src: value, + * }), + * }); + * + * // now resolution and format can be extracted from the url + * resolver.add('foo', [ + * 'image@2x.png' + * 'image.png' + * ]); + * @ + */ + public get parsers(): ResolveURLParser[] + { + return this._parsers; + } + + /** Used for testing, this resets the resolver to its initial state */ + public reset(): void + { + this._preferredOrder = []; + + this._resolverHash = {}; + this._assetMap = {}; + this._rootPath = null; + this._basePath = null; + this._manifest = null; + } + + /** + * Add a manifest to the asset resolver. This is a nice way to add all the asset information in one go. + * generally a manifest would be built using a tool. + * @param manifest - the manifest to add to the resolver + */ + public addManifest(manifest: ResolverManifest): void + { + if (this._manifest) + { + // #if _DEBUG + console.warn('[Resolver] Manifest already exists, this will be overwritten'); + // #endif + } + + this._manifest = manifest; + + manifest.bundles.forEach((bundle) => + { + this.addBundle(bundle.name, bundle.assets); + }); + } + + /** + * This adds a bundle of assets in one go so that you can resolve them as a group. + * For example you could add a bundle for each screen in you pixi app + * @example + * resolver.addBundle('animals', { + * bunny: 'bunny.png', + * chicken: 'chicken.png', + * thumper: 'thumper.png', + * }); + * + * const resolvedAssets = await resolver.resolveBundle('animals'); + * @param bundleId - The id of the bundle to add + * @param assets - A record of the asset or assets that will be chosen from when loading via the specified key + */ + public addBundle(bundleId: string, assets: ResolverBundle['assets']): void + { + const assetNames: string[] = []; + + if (Array.isArray(assets)) + { + assets.forEach((asset) => + { + if (typeof asset.name === 'string') + { + assetNames.push(asset.name); + } + else + { + assetNames.push(...asset.name); + } + + this.add(asset.name, asset.srcs); + }); + } + else + { + Object.keys(assets).forEach((key) => + { + assetNames.push(key); + this.add(key, assets[key]); + }); + } + + this._bundles[bundleId] = assetNames; + } + + /** + * Tells the resolver what keys are associated with witch asset. + * The most important thing the resolver does + * @example + * // single key, single asset: + * resolver.add('foo', 'bar.png'); + * resolver.resolveUrl('foo') // => 'bar.png' + * + * // multiple keys, single asset: + * resolver.add(['foo', 'boo'], 'bar.png'); + * resolver.resolveUrl('foo') // => 'bar.png' + * resolver.resolveUrl('boo') // => 'bar.png' + * + * // multiple keys, multiple assets: + * resolver.add(['foo', 'boo'], ['bar.png', 'bar.webp']); + * resolver.resolveUrl('foo') // => 'bar.png' + * + * // add custom data attached to the resolver + * Resolver.add( + * 'bunnyBooBooSmooth', + * 'bunny{png,webp}', + * {scaleMode:SCALE_MODES.NEAREST} // base texture options + * ); + * + * resolver.resolve('bunnyBooBooSmooth') // => {src: 'bunny.png', data: {scaleMode: SCALE_MODES.NEAREST}} + * @param keysIn - The keys to map, can be an array or a single key + * @param assetsIn - The assets to associate with the key(s) + * @param data - The data that will be attached to the object that resolved object. + */ + public add(keysIn: string | string[], assetsIn: string | ResolveAsset | (ResolveAsset | string)[], data?: unknown): void + { + const keys: string[] = convertToList(keysIn); + + keys.forEach((key) => + { + if (this._assetMap[key]) + { + // #if _DEBUG + console.warn(`[Resolver] already has key: ${key} overwriting`); + // #endif + } + }); + + if (!Array.isArray(assetsIn)) + { + if (typeof assetsIn === 'string') + { + assetsIn = createStringVariations(assetsIn); + } + else + { + assetsIn = [assetsIn]; + } + } + + const assetMap: ResolveAsset[] = assetsIn.map((asset): ResolveAsset => + { + let formattedAsset = asset as ResolveAsset; + + // check if is a string + if (typeof asset === 'string') + { + // first see if it contains any {} tags... + + let parsed = false; + + for (let i = 0; i < this._parsers.length; i++) + { + const parser = this._parsers[i]; + + if (parser.test(asset)) + { + formattedAsset = parser.parse(asset); + parsed = true; + break; + } + } + + if (!parsed) + { + formattedAsset = { + src: asset, + }; + } + } + + if (!formattedAsset.format) + { + formattedAsset.format = formattedAsset.src.split('.').pop(); + } + + if (!formattedAsset.alias) + { + formattedAsset.alias = keys; + } + + if (this._basePath || this._rootPath) + { + formattedAsset.src = utils.path.toAbsolute(formattedAsset.src, this._basePath, this._rootPath); + } + + formattedAsset.data = formattedAsset.data ?? data; + + return formattedAsset; + }); + + keys.forEach((key) => + { + this._assetMap[key] = assetMap; + }); + } + + /** + * If the resolver has had a manifest set via setManifest, this will return the assets urls for + * a given bundleId or bundleIds. + * @example + * // manifest example + * const manifest = { + * bundles:[{ + * name:'load-screen', + * assets:[ + * { + * name: 'background', + * srcs: 'sunset.png', + * }, + * { + * name: 'bar', + * srcs: 'load-bar.{png,webp}', + * } + * ] + * }, + * { + * name:'game-screen', + * assets:[ + * { + * name: 'character', + * srcs: 'robot.png', + * }, + * { + * name: 'enemy', + * srcs: 'bad-guy.png', + * } + * ] + * }] + * }} + * resolver.setManifest(manifest); + * const resolved = resolver.resolveBundle('load-screen'); + * @param bundleIds - The bundle ids to resolve + * @returns All the bundles assets or a hash of assets for each bundle specified + */ + public resolveBundle(bundleIds: string | string[]): + Record | Record> + { + const singleAsset = isSingleItem(bundleIds); + + bundleIds = convertToList(bundleIds); + + const out: Record> = {}; + + bundleIds.forEach((bundleId) => + { + const assetNames = this._bundles[bundleId]; + + if (assetNames) + { + out[bundleId] = this.resolve(assetNames) as Record; + } + }); + + return singleAsset ? out[bundleIds[0]] : out; + } + + /** + * Does exactly what resolve does, but returns just the URL rather than the whole asset object + * @param key - The key or keys to resolve + * @returns - The URLs associated with the key(s) + */ + public resolveUrl(key: string | string[]): string | Record + { + const result = this.resolve(key); + + if (typeof key !== 'string') + { + const out: Record = {}; + + for (const i in result) + { + out[i] = (result as Record)[i].src; + } + + return out; + } + + return (result as ResolveAsset).src; + } + + /** + * Resolves each key in the list to an asset object. + * Another key function of the resolver! After adding all the various key/asset pairs. this will run the logic + * of finding which asset to return based on any preferences set using the `prefer` function + * by default the same key passed in will be returned if nothing is matched by the resolver. + * @example + * resolver.add('boo', 'bunny.png'); + * + * resolver.resolve('boo') // => {src:'bunny.png'} + * + * // will return the same string as no key was added for this value.. + * resolver.resolve('another-thing.png') // => {src:'another-thing.png'} + * @param keys - key or keys to resolve + * @returns - the resolve asset or a hash of resolve assets for each key specified + */ + public resolve(keys: string | string[]): ResolveAsset | Record + { + const singleAsset = isSingleItem(keys); + + keys = convertToList(keys); + + const result: Record = {}; + + keys.forEach((key) => + { + if (!this._resolverHash[key]) + { + if (this._assetMap[key]) + { + let assets = this._assetMap[key]; + + const preferredOrder = this._getPreferredOrder(assets); + + const bestAsset = assets[0]; + + preferredOrder?.priority.forEach((priorityKey) => + { + preferredOrder.params[priorityKey].forEach((value: unknown) => + { + const filteredAssets = assets.filter((asset) => + { + if (asset[priorityKey]) + { + return asset[priorityKey] === value; + } + + return false; + }); + + if (filteredAssets.length) + { + assets = filteredAssets; + } + }); + }); + + this._resolverHash[key] = (assets[0] ?? bestAsset); + } + else + { + let src = key; + + if (this._basePath || this._rootPath) + { + src = utils.path.toAbsolute(src, this._basePath, this._rootPath); + } + + // if the resolver fails we just pass back the key assuming its a url + this._resolverHash[key] = { + src, + }; + } + } + + result[key] = this._resolverHash[key]; + }); + + return singleAsset ? result[keys[0]] : result; + } + + /** + * Internal function for figuring out what prefer criteria an asset should use. + * @param assets + */ + private _getPreferredOrder(assets: ResolveAsset[]): PreferOrder + { + for (let i = 0; i < assets.length; i++) + { + const asset = assets[0]; + + const preferred = this._preferredOrder.find((preference: PreferOrder) => + preference.params.format.includes(asset.format)); + + if (preferred) + { + return preferred; + } + } + + return this._preferredOrder[0]; + } +} diff --git a/packages/assets/src/resolver/index.ts b/packages/assets/src/resolver/index.ts new file mode 100644 index 00000000000..1170eb609e7 --- /dev/null +++ b/packages/assets/src/resolver/index.ts @@ -0,0 +1,3 @@ +export * from './types'; +export * from './parsers'; +export type { Resolver } from './Resolver'; diff --git a/packages/assets/src/resolver/parsers/index.ts b/packages/assets/src/resolver/parsers/index.ts new file mode 100644 index 00000000000..5bfaab81e2f --- /dev/null +++ b/packages/assets/src/resolver/parsers/index.ts @@ -0,0 +1 @@ +export * from './resolveTextureUrl'; diff --git a/packages/assets/src/resolver/parsers/resolveTextureUrl.ts b/packages/assets/src/resolver/parsers/resolveTextureUrl.ts new file mode 100644 index 00000000000..9ad60fd2c2e --- /dev/null +++ b/packages/assets/src/resolver/parsers/resolveTextureUrl.ts @@ -0,0 +1,17 @@ +import { settings, extensions, ExtensionType } from '@pixi/core'; +import { loadTextures } from '../../loader'; + +import type { ResolveAsset, ResolveURLParser } from '../types'; + +export const resolveTextureUrl = { + extension: ExtensionType.ResolveParser, + test: loadTextures.test, + parse: (value: string): ResolveAsset => + ({ + resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + format: value.split('.').pop(), + src: value, + }), +} as ResolveURLParser; + +extensions.add(resolveTextureUrl); diff --git a/packages/assets/src/resolver/types.ts b/packages/assets/src/resolver/types.ts new file mode 100644 index 00000000000..72412a288cf --- /dev/null +++ b/packages/assets/src/resolver/types.ts @@ -0,0 +1,66 @@ +import type { ExtensionMetadata } from '@pixi/core'; + +/** + * A prefer order lets the resolver know which assets to prefer depending on the various parameters passed to it. + * @memberof PIXI + */ +export interface PreferOrder +{ + /** the importance order of the params */ + priority?: string[]; + params: { + [key: string]: any; + }; +} + +/** + * the object returned when a key is resolved to an asset. + * it will contain any additional information passed in the asset was added. + * @memberof PIXI + */ +export interface ResolveAsset extends Record +{ + alias?: string[]; + src: string; +} + +export type ResolverAssetsArray = { + name: string | string[]; + srcs: string | ResolveAsset[]; +}[]; + +export type ResolverAssetsObject = Record; + +/** + * Structure of a bundle found in a manfest file + * @memberof PIXI + */ +export interface ResolverBundle +{ + name: string; + assets: ResolverAssetsArray | ResolverAssetsObject +} + +/** + * The expected format of a manifest. This would normally be auto generated ar made by the developer + * @memberof PIXI + */ +export type ResolverManifest = { + // room for more props as we go! + bundles: ResolverBundle[]; +}; + +/** + * Format for url parser, will test a string and if it pass will then parse it, turning it into an ResolveAsset + * @memberof PIXI + */ +export interface ResolveURLParser +{ + extension?: ExtensionMetadata; + /** A config to adjust the parser */ + config?: Record + /** the test to perform on the url to determin if it should be parsed */ + test: (url: string) => boolean; + /** the function that will convert the url into an object */ + parse: (value: string) => ResolveAsset; +} diff --git a/packages/assets/src/utils/convertToList.ts b/packages/assets/src/utils/convertToList.ts new file mode 100644 index 00000000000..8154d76b6c0 --- /dev/null +++ b/packages/assets/src/utils/convertToList.ts @@ -0,0 +1,22 @@ +export const convertToList = (input: string | T | (string | T)[], transform?: (input: string) => T): T[] => +{ + if (!Array.isArray(input)) + { + input = [input as T]; + } + + if (!transform) + { + return input as T[]; + } + + return (input as (string | T)[]).map((item): T => + { + if (typeof item === 'string') + { + return transform(item as string); + } + + return item as T; + }); +}; diff --git a/packages/assets/src/utils/createStringVariations.ts b/packages/assets/src/utils/createStringVariations.ts new file mode 100644 index 00000000000..1f2c2d9658b --- /dev/null +++ b/packages/assets/src/utils/createStringVariations.ts @@ -0,0 +1,55 @@ +function processX(base: string, ids: string[][], depth: number, result: string[], tags: string[]) +{ + const id = ids[depth]; + + for (let i = 0; i < id.length; i++) + { + const value = id[i]; + + if (depth < ids.length - 1) + { + processX(base.replace(result[depth], value), ids, depth + 1, result, tags); + } + else + { + tags.push(base.replace(result[depth], value)); + } + } +} + +/** + * Creates a list of all possible combinations of the given strings. + * @example + * const out2 = createStringVariations('name is {chicken,wolf,sheep}'); + * console.log(out2); // [ 'name is chicken', 'name is wolf', 'name is sheep' ] + * @param string - The string to process + */ +export function createStringVariations(string: string): string[] +{ + const regex = /\{(.*?)\}/g; + + const result = string.match(regex); + + const tags: string[] = []; + + if (result) + { + const ids: string[][] = []; + + result.forEach((vars) => + { + // first remove the brackets... + const split = vars.substring(1, vars.length - 1).split(','); + + ids.push(split); + }); + + processX(string, ids, 0, result, tags); + } + else + { + tags.push(string); + } + + return tags; +} diff --git a/packages/assets/src/utils/index.ts b/packages/assets/src/utils/index.ts new file mode 100644 index 00000000000..e6ab8872929 --- /dev/null +++ b/packages/assets/src/utils/index.ts @@ -0,0 +1,3 @@ +export * from './convertToList'; +export * from './createStringVariations'; +export * from './isSingleItem'; diff --git a/packages/assets/src/utils/isSingleItem.ts b/packages/assets/src/utils/isSingleItem.ts new file mode 100644 index 00000000000..2c6c4fcdf2e --- /dev/null +++ b/packages/assets/src/utils/isSingleItem.ts @@ -0,0 +1,5 @@ +/** + * Checks if the given value is an array. + * @param item - The item to test + */ +export const isSingleItem = (item: unknown): boolean => (!Array.isArray(item)); diff --git a/packages/assets/test/assets.tests.ts b/packages/assets/test/assets.tests.ts new file mode 100644 index 00000000000..016fb584204 --- /dev/null +++ b/packages/assets/test/assets.tests.ts @@ -0,0 +1,364 @@ +import { BaseTexture, Texture } from '@pixi/core'; +import { Spritesheet } from '@pixi/spritesheet'; + +import { Assets } from '@pixi/assets'; + +function wait(value = 500) +{ + // wait a bit... + return new Promise((resolve) => + setTimeout(() => resolve(), value)); +} + +describe('Assets', () => +{ + const basePath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/assets/test/assets/` + : 'http://localhost:8080/assets/test/assets/'; + + beforeEach(() => + { + // reset the loader + Assets.reset(); + }); + + it('should load assets', async () => + { + await Assets.init({ + basePath, + }); + + const bunny = await Assets.load('textures/bunny.png'); + + expect(bunny).toBeInstanceOf(Texture); + }); + + it('should get assets once loaded', async () => + { + await Assets.init({ + basePath, + }); + + Assets.add('test', 'textures/bunny.png'); + + // not loaded yet! + const bunny0 = Assets.get('test'); + + expect(bunny0).toBe(undefined); + + const bunny = await Assets.load('test'); + + const bunny2 = Assets.get('test'); + + expect(bunny).toBeInstanceOf(Texture); + expect(bunny2).toBe(bunny); + }); + + it('should load a webp if available by default', async () => + { + await Assets.init({ + basePath, + texturePreference: { + resolution: 2, + }, + }); + + Assets.add('test', [ + 'textures/profile-abel@0.5x.jpg', + 'textures/profile-abel@2x.jpg', + 'textures/profile-abel@0.5x.webp', + 'textures/profile-abel@2x.webp', + ]); + + // not loaded yet! + const bunny = await Assets.load('test'); + + expect(bunny.baseTexture.resource.src).toBe(`${basePath}textures/profile-abel@2x.webp`); + }); + + it('should load a correct texture based on preference', async () => + { + await Assets.init({ + basePath, + texturePreference: { + format: 'jpg', + resolution: 2, + }, + }); + + Assets.add('test', [ + 'textures/profile-abel@0.5x.jpg', + 'textures/profile-abel@2x.jpg', + 'textures/profile-abel@0.5x.webp', + 'textures/profile-abel@2x.webp', + ]); + + // not loaded yet! + const bunny = await Assets.load('test'); + + expect(bunny.baseTexture.resource.src).toBe(`${basePath}textures/profile-abel@2x.jpg`); + }); + + it('should add and load bundle', async () => + { + await Assets.init({ + basePath, + }); + + Assets.addBundle('testBundle', { + bunny: 'textures/bunny.{png,webp}', + spritesheet: 'spritesheet/spritesheet.json', + }); + + const assets = await Assets.loadBundle('testBundle'); + + expect(assets.bunny).toBeInstanceOf(Texture); + expect(assets.spritesheet).toBeInstanceOf(Spritesheet); + }); + + it('should load a bundle found in the manifest', async () => + { + await Assets.init({ + basePath, + manifest: 'json/asset-manifest-2.json', + }); + + const assets = await Assets.loadBundle('default'); + + expect(assets.bunny).toBeInstanceOf(Texture); + expect(assets['profile-abel']).toBeInstanceOf(Texture); + expect(assets.spritesheet).toBeInstanceOf(Spritesheet); + }); + + it('should load multiple bundles', async () => + { + await Assets.init({ + basePath, + manifest: 'json/asset-manifest-2.json', + }); + + const progressMock = jest.fn(); + + const assets = await Assets.loadBundle(['default', 'data'], progressMock); + + expect(progressMock).toHaveBeenCalledTimes(4); + expect(progressMock.mock.calls).toEqual([[0.25], [0.5], [0.75], [1]]); + expect(assets.default.bunny).toBeInstanceOf(Texture); + expect(assets.default['profile-abel']).toBeInstanceOf(Texture); + expect(assets.default.spritesheet).toBeInstanceOf(Spritesheet); + + expect(assets.data[`test.json`]).toEqual({ testNumber: 23, testString: 'Test String 23' }); + }); + + it('should map all names', async () => + { + await Assets.init({ + basePath, + }); + + Assets.add(['fish', 'chicken'], 'textures/bunny.png'); + + const bunny = await Assets.load('fish'); + + // this should be the same as bunny + const bunny2 = await Assets.get('chicken'); + + expect(bunny).toBeInstanceOf(Texture); + expect(bunny).toBe(bunny2); + }); + + it('should split url versions correctly', async () => + { + await Assets.init({ + basePath, + }); + + Assets.add('fish', 'textures/bunny.{png,webp}'); + + const bunny = await Assets.load('fish'); + + expect(bunny.baseTexture.resource.src).toBe(`${basePath}textures/bunny.webp`); + }); + + it('should background load correctly', async () => + { + await Assets.init({ + basePath, + }); + + Assets.backgroundLoad(['textures/bunny.png']); + + // wait a bit... + await wait(); + + const asset = await Assets.loader.promiseCache[`${basePath}textures/bunny.png`].promise; + + expect(asset).toBeInstanceOf(Texture); + expect(asset.baseTexture.resource.src).toBe(`${basePath}textures/bunny.png`); + }); + + it('should background load bundles', async () => + { + await Assets.init({ + basePath, + manifest: 'json/asset-manifest-2.json', + }); + + Assets.backgroundLoadBundle('default'); + + // wait a bit... + await wait(); + + const expectTypes = { + 'json/asset-manifest-2.json': Object, + 'textures/bunny.png': Texture, + 'textures/profile-abel@2x.webp': Texture, + 'spritesheet/spritesheet.json': Spritesheet, + 'spritesheet/spritesheet.png': Texture, + }; + + for (const [key, type] of Object.entries(expectTypes)) + { + const asset = await Assets.loader.promiseCache[basePath + key].promise; + + expect(asset).toBeInstanceOf(type); + } + }); + + it('should error out if loader fails', async () => + { + Assets.load('chickenSandwich.png').catch((e) => + { + expect(e).toBeInstanceOf(Error); + }); + }); + + it('should add sprite textures to the cache', async () => + { + await Assets.init({ + basePath, + }); + + await Assets.load('spritesheet/spritesheet.json'); + + const texture = Assets.get('pic-sensei.jpg'); + + expect(texture).toBeInstanceOf(Texture); + }); + + it('should dispose of a texture correctly', async () => + { + await Assets.init({ + basePath, + }); + + const bunny = await Assets.load('textures/bunny.png') as Texture; + + bunny.destroy(true); + + expect(bunny.baseTexture).toBe(null); + + const bunnyReloaded = await Assets.load('textures/bunny.png') as Texture; + + expect(bunnyReloaded.baseTexture).toBeInstanceOf(BaseTexture); + }); + + it('should load texture array correctly', async () => + { + await Assets.init({ + basePath, + }); + + const pathsToLoad = ['textures/bunny.png', 'textures/profile-abel@2x.jpg']; + + const assets = await Assets.load(pathsToLoad); + + for (const path of pathsToLoad) + { + expect(assets[path]).toBeInstanceOf(Texture); + } + }); + + it('should unload and remove from the cache correctly', async () => + { + await Assets.init({ + basePath, + }); + + Assets.add(['chickenSheet', 'alias'], 'spritesheet/spritesheet.json'); + + await Assets.load('chickenSheet'); + + const texture = Assets.get('pic-sensei.jpg'); + + expect(texture).toBeInstanceOf(Texture); + + await Assets.unload('chickenSheet'); + + const texture2 = Assets.get('pic-sensei.jpg'); + + expect(texture2).toBe(undefined); + }); + + it('should unload assets correctly', async () => + { + await Assets.init({ + basePath, + }); + + const bunny = await Assets.load('textures/bunny.png') as Texture; + + await Assets.unload('textures/bunny.png'); + + expect(bunny.baseTexture).toBe(null); + }); + + it('should unload bundles correctly', async () => + { + await Assets.init({ + basePath, + }); + + Assets.addBundle('testBundle', { + bunny: 'textures/bunny.{png,webp}', + spritesheet: 'spritesheet/spritesheet.json', + }); + + const assets = await Assets.loadBundle('testBundle'); + + expect(assets.bunny).toBeInstanceOf(Texture); + expect(assets.spritesheet).toBeInstanceOf(Spritesheet); + + await Assets.unloadBundle('testBundle'); + + expect(assets.bunny.baseTexture).toBe(null); + }); + + it('should load PNG base64 assets', async () => + { + // Other formats (JPG, JPEG, WEBP, AVIF) can be added similarly. + let bunnyBase64 = ` + data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAkGBggGBQkIBwgKCQkKDRYODQwMDRoTFBAWHxwhIB8c + Hh4jJzIqIyUvJR4eKzssLzM1ODg4ISo9QTw2QTI3ODX/2wBDAQkKCg0LDRkODhk1JB4kNTU1NTU1NTU1NTU1NTU1NTU1NTU1NT + U1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTX/wgARCAAlABoDAREAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABgUHBP/E + ABkBAAMBAQEAAAAAAAAAAAAAAAIDBAUBBv/aAAwDAQACEAMQAAAAfoMjG9G5byxWYwUHfPaNTTmebMAqZ1zJphvFntQwkNP49f + dWrUdeIEs1xcBAWmGH/8QANRAAAQMCBAQDAg8AAAAAAAAAAgEDBAURAAYSEwcUIWEQFSIxUjI0NkJFVFVicXWBoqTCw//aAAgB + AQABPwDiRsHGobM3rBfqoBKb+abaNOlYk/Eb4qz8Cmee0mhjsQpnJIwywC7J6XV5nsl27It/h4y6xSIHEFlnLjLLEN+mPG8DCa + BMxcZ037oh+Gd810nMgQIlIkrKciTleds0aBoRp0LoappLqSexcMsTtp0xjPSmWiu6+KtiLaGSoKKikirbsmMpVFqhV2NLqLjp + gEN5g3WoxuKpkTCp6ARVS+2eEz7lv7bgB9x19AMeyivVFxxGyrScswoE6jxliPvz9o7PHo0K06VkBV0j1HFAybCqFGalSTdU3e + vpW1sUygRJ+fjo07dditRX3LA8bSqYG0KLcFRfYZYHIGWg+g4B93GdZfqS9Vxxk+T9J/M/8H8QuKjNBY5BX4jmz7xpcMZCqPm3 + EMZmtHN+myTund1jw4zhbIwzvqEsH9Hv3Qm/74oFO8oy5TqfubvKRWmNdratIoN7YyRTdji/mj1/E9f8lxHv228P/8QAHxEAAg + IDAAMBAQAAAAAAAAAAAQIAAwQREgUQIRRR/9oACAECAQE/AL2CoWJi5VfJJaY1osJ0dzqZ1qikgwVJYpcHWp426sM4Hydj+zMr + U0kzGwBbV0TPHY6qz7nCzL+0tqUfqRNBfk8cGBfv1YNrqARF0xPr/8QAHhEAAgICAwEBAAAAAAAAAAAAAQIAAxESBBAhMTL/2g + AIAQMBAT8AQEnAgqckSxWA9646HfML6kLOUjEAzQyh23xLeQVbAl9hKjE3Mp/Yli1M32cnGAB0h9hhPnX/2Q== + `; + + // to prevent eslint max-len warning + bunnyBase64 = bunnyBase64.replace(/\s/g, ''); + + Assets.add('bunny', bunnyBase64); + const bunny = await Assets.load('bunny'); + + expect(bunny).toBeInstanceOf(Texture); + }); +}); diff --git a/packages/assets/test/assets/fonts/outfit.woff2 b/packages/assets/test/assets/fonts/outfit.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..90597af2e8135b4fd576b7e0e3a3db4ac136cd02 GIT binary patch literal 35084 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 VPSxwx>AU@(TvYn&xAeaN004S%>wN$K literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/json/asset-manifest-2.json b/packages/assets/test/assets/json/asset-manifest-2.json new file mode 100644 index 00000000000..2855d9efa58 --- /dev/null +++ b/packages/assets/test/assets/json/asset-manifest-2.json @@ -0,0 +1,52 @@ +{ + "bundles": [ + { + "name": "default", + "assets": [ + { + "name": "bunny", + "srcs": [ + { + "resolution": 1, + "format": "png", + "src": "textures/bunny.png" + } + ] + }, + { + "name": "spritesheet", + "srcs": [ + { + "resolution": 1, + "format": "png", + "src": "spritesheet/spritesheet.json" + }, + { + "resolution": 1, + "format": "png", + "src": "spritesheet/spritesheet.json" + } + ] + }, + { + "name": "profile-abel", + "srcs": [ + "textures/profile-abel@0.5x.jpg", + "textures/profile-abel@2x.webp", + "textures/profile-abel@0.5x.jpg", + "textures/profile-abel@2x.webp" + ] + } + ] + }, + { + "name": "data", + "assets": [ + { + "name": "test.json", + "srcs": "json/test.json" + } + ] + } + ] +} diff --git a/packages/assets/test/assets/json/asset-manifest.json b/packages/assets/test/assets/json/asset-manifest.json new file mode 100644 index 00000000000..b149b8417a3 --- /dev/null +++ b/packages/assets/test/assets/json/asset-manifest.json @@ -0,0 +1,47 @@ +{ + "bundles": [ + { + "name": "default", + "assets": [ + { + "name": "bunny", + "srcs": [ + { + "resolution": 1, + "format": "png", + "src": "textures/bunny.png" + } + ] + }, + { + "name": "spritesheet", + "srcs": [ + { + "resolution": 1, + "format": "png", + "src": "spritesheet/spritesheet.json" + } + ] + }, + { + "name": "profile-abel", + "srcs": [ + "textures/profile-abel@0.5x.jpg", + "textures/profile-abel@2x.webp", + "textures/profile-abel@0.5x.jpg", + "textures/profile-abel@2x.webp" + ] + } + ] + }, + { + "name": "data", + "assets": [ + { + "name": "test.json", + "srcs": "json/test.json" + } + ] + } + ] +} diff --git a/packages/assets/test/assets/json/test.json b/packages/assets/test/assets/json/test.json new file mode 100644 index 00000000000..e0ebf283f1b --- /dev/null +++ b/packages/assets/test/assets/json/test.json @@ -0,0 +1,4 @@ +{ + "testNumber": 23, + "testString": "Test String 23" +} diff --git a/packages/assets/test/assets/spritesheet/multi-pack-0.json b/packages/assets/test/assets/spritesheet/multi-pack-0.json new file mode 100644 index 00000000000..e05acdb9da8 --- /dev/null +++ b/packages/assets/test/assets/spritesheet/multi-pack-0.json @@ -0,0 +1,48 @@ +{"frames": { + +"star1.png": +{ + "frame": {"x":0,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star2.png": +{ + "frame": {"x":64,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star3.png": +{ + "frame": {"x":128,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star4.png": +{ + "frame": {"x":192,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}}, +"animations": { + "star": ["star1.png","star2.png","star3.png","star4.png"] +}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "multi-pack-0.png", + "format": "RGBA8888", + "size": {"w":256,"h":64}, + "scale": "1", + "related_multi_packs": [ "multi-pack-1.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:5f1e3e3af16b7f3e5f4097ccfd45634f:8acde9d234ecca966a410602c71bffad:e9ee6f100f514069f43ab3a680b02726$" +} +} diff --git a/packages/assets/test/assets/spritesheet/multi-pack-0.png b/packages/assets/test/assets/spritesheet/multi-pack-0.png new file mode 100644 index 0000000000000000000000000000000000000000..52c1171d0156238ca9f9a7787f047257c63f0ec9 GIT binary patch literal 2435 zcmV-}34Hd6P)UDWP;i z$aG2>p_EJsWz)G+Mku8-GM$ntnNFwG$&^g0)5>&GsZJ)-Y9&&cXMfz2_TJn3@xJdp zAHVbFJRB-@-+O-_?>WEk0|W#F1Ox;G1Ox;G1Ox;G1Ox;G1O%7_^MMBeX;<>Dz=N86 z*$ePS;6q*hv;`jcFT{3$F97Zjyr|$y4&Wj{0-Ol^sNhW&U=iSS;D!If992rb1@Lg- z$7{ZvR(v7Ab%33LCp#_?XBA(T0zdp0=vO5Lvb^2fnZk;LR$&bbIpK zhwL11%mEzsMW6+M8&v`&z*D>2yuDL{Cj@wK7xSg7bmG6o6HnYD9#_A2!Hm1h9Kdma zs{n8LX8zY&yVSqqsRle*-kn(i_5oa}!xK+}q&!*myXOH8XgV;)06r>v_JS{hoo%4( z1o&-%*LbE6u@UC$nE!m+_hnAg zPANQX^p<~HYi$AS7f#19O{d$Th&nRrfxe$>vWd+^Plt09;DZLwd*s6ga5#csch+2d z)0cf}hb$_;i^+FdEBu&YoLy=|nJ)Q+HO=UC!Mx~>VETI${NhxD-@T+Z<)if@ z_&gJn7whs}#aR0OO!1&lW(h6E`@DSf|5;2SQ!!yrDT>NTfLB!1Gs}2RDTrULjXSm*i?Ue31l9+Rrbt30RIBe zWARHzgr9o01JDHk&s&zHffpnTU=4uH)XggZ?*W-j1N5{3SaBfWsQ9x?5nchfSN4BD z0GXc*ZG^J`j##Gk10Zuxs0FYLpx5FTz7J&nmdJ>M4$Q+lhG{zEfTmX03$tCA4GWrf znVSayT(iszEhWvUXLc5jeH!n=# zEu_m>Xi~B&X?<=<9~OnsdtbR}eGU&p+cewi2;`tD{8$pI?8_DfJ?X*AzpAISIubu- z1k(RN>FZvLdU4bNou)HwJO}Wp2MT}DqM!>7f<1AU#d!-H6V8iA0MC{VF(dSMMre35 zwYC&(Ig=;R5@mmbfi5oB`FPD((FvXqEZi+O12jZh0e2kmp-s4(xKt`z z)|T~{t})6@n#*His+8zL7zg$8%nMZfeGYiAApB*}R0zcbRTFunuS*7IV?^qAc4+=s z-vmwyqJPdo-g{nnCPYJh06SDCBRyPenllB=mRfGb5 zhKWiX6B6WWbzRk15-#5CvphPg;b4rEx2A>=*1Kt(k2S5##?`3Id8w1+z4z*r=?}3Qzyl zOMwoVJ{9%}t`=O@mjm{q4!~5o>!|QzuoITtpZTmK zf%69BJ0kq#vpgP~*;1#aSe>7@+#bzAPwK!m?uI-om{yG@ABR2Z1#vJrnY|8%fHre^ zU0j|bsu;#Xs*Ih&Yu`29qsN@^T))HqhYCK83y6bVba*3{cqO^3%9u4>wZ)xja>=v1klk1==!b%ajC#)rJ%UOR87e zzYCrAU0pqBl~?_WDA@5JlHn@bw9DBTgbgAM@Q29)iO8h`&Az>~L4)68Sb z4BNTK(58txxXU(xm#)qK0}jl*X?O<~TFjK(u{-3`TbF6e-YE3CG+VCock2Qqxs>1` zfFE1P?FnT3tg^6$1FF(=Hlh`E(lO0z2{KvZYN$-y?8$YP zgjSD&exd5^r&T&ALIDmB$1El(dcFa4#T4?QpQe8W&9`FC@M{uNVz;`1r&#Bfs!NXP zU5P>KM5W8Zc12gzcVgBhp*<=Ec)Ycl{M;Yor5J|yh}=SKdB&eHdM9I)v?d6YvY@QX zDP@t~bxiMrCUibk6{`6rn_QHUYZs9Ya4405)ogx;kF zoq8wZ74ERFNuNy-=>hwi%-Fw>B3cKU_{I<1N3*rk`>4sZ+I)&=y;Y+`{Zwn^=^Rw< zbxIG3O1Gk(vK&Ymt;GhW|4_#>RS&V1f z{!PxQ)Saw=PC%ms=F92~Mp8`YoW1s4=O^QanX%mgX;qq>N;T$FOyf>%z)Z?zc`zMm z+<*Z6FUPU;q`?9L0s;a80s;a80s;a80s;c0;(rKYI3Kg$!;1g_002ovPDHLkV1nza Bj$i-) literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/spritesheet/multi-pack-1.json b/packages/assets/test/assets/spritesheet/multi-pack-1.json new file mode 100644 index 00000000000..ff4c21ff7b1 --- /dev/null +++ b/packages/assets/test/assets/spritesheet/multi-pack-1.json @@ -0,0 +1,23 @@ +{"frames": { + +"goldmine_10_5.png": +{ + "frame": {"x":0,"y":0,"w":190,"h":229}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":190,"h":229}, + "sourceSize": {"w":190,"h":229} +}}, +"animations": { +}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "multi-pack-1.png", + "format": "RGBA8888", + "size": {"w":190,"h":229}, + "scale": "1", + "related_multi_packs": [ "multi-pack-0.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:5f1e3e3af16b7f3e5f4097ccfd45634f:8acde9d234ecca966a410602c71bffad:e9ee6f100f514069f43ab3a680b02726$" +} +} diff --git a/packages/assets/test/assets/spritesheet/multi-pack-1.png b/packages/assets/test/assets/spritesheet/multi-pack-1.png new file mode 100644 index 0000000000000000000000000000000000000000..639b33f660e934acaf06a86ff945d63d730b2e9a GIT binary patch literal 69086 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 s$8|d{ zX4|@zNTryaoon&r*&nvAxMX0}%&a=w*AFg4qae%k?CgMv8F=)8<8(wDXj$2Xrd%e+ zW>~v@6MZL6kxeEE)?Nfw(-In&fd5Mz5;2c`AN;Cvr)=@dk9mNh&EuWyoEi{x|qR|jnY+cXVl|Ae_c#I!Ex{Kc9r+NL=m(ktcLMoG? zR5Cj^U3w!;o##1oY(K;2rwD~16!zy}nqb93NMRCA5+E&Yq{Lv4LQ; z7P8qTG%f-E7Z0__8&|$|ZQ+4=i|*@uJS7miLTGaSHHt+VAPGwIcLS-w&@_Z5n3_wG zOlN7XucfP_l~U0r8Vz&Pb(eGb*7ZE__+Gwt_x)^Mx035G+eRX4kxnIPXk121OE(wJ z9OwAq-ONmvh$Z~bvx^SVL>2i|mPjm0ye2{KlY7y1gND{dbi=~7Q%h+4PaN7yZpLB} zy%CF6MER!ju=1cfqLC|U%;a>0s6>Jm0$Hjog8()Eo~CJnrZF@=$-YC!IdN`)iJ2th zle5GkLEih8*YUpFZenUC$rrwP4?7PWBNhpvoE)iChMqNBxb6*aW6SoYN*O!S#qnbd(gR@(vkI@oa0 z3NpC@JA02aFf>L(Z8Z(maZ>3y%wUWaYt|EqHqp@FEpQ6{6<)I1;F2z#Vld2O=~_Pj^;t$|3N+V*2nQ6N6bMa26QFAXAvAv> z;6H{Y5C~k?!_+mJ8|&z3X{0(HBOZ%T6^}8S$+5flIOi@5(%xLpj;-sdPQ=ON@(3eA zED@zK+)uFZBsH-No$EGX1QQes4u#26B+Th`oo~-Rrv%nDufJt`Q+>-P8?@n@UUki8 z3gPWvTDD^4pI^Fh#qbieUv3;9UxxfNZeOPAQZ4X*DFvaRARZDpE}R`#SenCs|C0uG z@4t}`zO9{P)?s9>LU*Je4U!<0EWf8JM~-}N*f2CCilNa7_8&gUu`}lx9-CxzVv3-l zbJMk#aoZcNMGC>c-v0=XJhdNP*N6s6OpFcF+gHo!^o?YLHxP_fVToBr&Yos`c#65% z=k|Ya!&R4DJ3BqS8zXd6er}SmRbt(y%^xZz$9}#9>z5hT37OoXYpfP!;EOUviJ1_z z{0NFcC3`C{07F;AqdL)`023PP6V$KW!cDh0bj}RW*DvLG4k4t2rtA2&ePKWJsZYfR z@PF4d9ZyPTlPSihX2=&yC~obFAWVEO`Ub0`|Mq*|B$NOdFP$ly0*k$wAWXEK^4;4g$rkC-FgeL+HDN? zKER%b?yb3E!}1$%z43;@2cOv6w*>K*0r0~*cWAnwxve<3LO{%dkmXx?Ln{l_gg^%j zU66S}TBMeNoGCEYZ;w`Vg;oyA_Kl%$v&+okB=D!LA17DO<)f&2vkWg|xB9RF3poLNp ziN^_A7KUknQb^BPCJ^tr_4U`Rx#ikdo%!J-PfRR9{-qezvA9Fi{HTsriOZKQe%LC< z%gf+5b&2I1 z8afkWqvUfLgs!1!S_Sp<`iM%tphApFrM9pU`Y7)|vxbTmiFX7l9onTvGI`N-`zT_1V-dXO$^KY0 z5+N3epgjNcb=~KDp3=}Y4c*i*4Fkh4F$@Du)BGt*xh@z8eE7B-uaA8Hfk%I~1pAj7 z)iJq4gVp+?jI9t5wICc=2xl4wm;!XAA#_N@1QAOo7=+dpHH5pnaVAC?I5fh%QnkAPnAQhAf zCBi|A^{bcB-OPaoa8?V{zI zJC8V(Z)2mA%7d@G>o8iuZw0k31|I)-IpStc3+$99l{9dEno)o=X0 z-+X89KmFT%BLIK(<-1ltc>niaabeJxR5-IPz`cgfE!I52_krISf%+II9V`LC0E9HK zl!jqJN25k#)TAmQ*?!Y9nqGY!*&~N|@|*iOakj`V`%;Dq)u_S@rBVr{6v0p!-7qL- z(iGFPICh~N=F}EBx(g1k5Tfh`EP7HZq?G8IMq_;qovqC@)h4K^sV0#~Fg7*ILr?Cd ze_({o7cJ+?OE+U#2D8aD;b4eZBKE}I-s9c-kDP3io+KI$;ChN!Bt%C`BW(Xa*WOLKjpr)b%xS@>=*G4xAp3Ua`66ZS~!ozH4iZzk9S9DPv8DsFs zD6>hAT>}~yCh~ZtERN&gI1YtE{!AgC`?=KhuN#5TpXhiGDc4!2ppHcV7mH*QYW{A8 z{w%yMnNBk{IZeJ$LZK)Xi`2%WY}v4y+S+RN9X`d*eTNAIEtYk*Aq1q7na-Y$ws?0( zD@wuG)XaPZ{^ay5*=&J;Wl$Z9`m$;Sy3o-y4a3kdbl>`Gx`wXln5IEE6l7**mXp)o z)^swrUJm_`jXPd-k*6Bh|I=4L|IJql@LzJWWTk=Bp7DD*cCV=gDlVzWlzmGlgfAEN zTnV@+&qYeVb5*9`O%zM^o``Ud3SB?wd0y|pz`%uPeEKfnUsty`{DD;JlS)zT3y1t{ zh(gUrfGUbmKO-y<8km-al8U~;QAQ@F=xl4Er@e*R>I4_{bg-(YlU)an^7EYs+1GoL zS6_7rD|!6jL+t|Fthvx1WRjWJ64^J>~Y=TV2V<2PRdiwmxr<1AFBXe_eCsV0Z^4aDv zozCs5jaGe47b>7omn!^<81W3+|4c!gL?MI^JWnbnrsf!%n!)uXQhJ!0V8cbr*t&5o z)5#1EKDL{o(Q(?E>#2%I$>j3XRVP@{)8T`DE=4AnBVd`NGFc|3X7F5(L@Y`?7F`Iv zYQDACO&uWwg_2Do5$E!aE0~%X<=o&9b92*VGTD>6o_gXNOThniq&m8<)zR@QtwhA56IDID7-8V<5)?MiyO z+UXx2=Vy=YA)71E)!u|@=#)whovqDuceD`-hnP+#$rp;4hQZ|Y9Ane7c+#Uf9w#1; zmnS0eqz6KyrKN>fG(sVpW@K=P)5DWQV{vAZ#Z$))?Y(OW_`jyWS01Ycpvu8M&G3O= z4s!U)%Cf~50t`bV7SRY>f`9=n-7%^!>Y^|>PXCb!Mw0@eY2W_&8Tp)(JhQ3nRBO~d z7$E=KO6a&)Cf`)z+}P z_c%}P>BZ1>I@+52K0^Xlba$|-rw2{f8Jn0wDTxBcCZ-shn5I-JQD0Y0AP^uLiP7BB zOfs2d@810!ICzBVbcUpiF){1VRg=AU|H0$0m{8|SisP4ToOnD$sJb4chssUk78jD8 zN|gD2CESi*YKQ`<6s`j4`A@EkYDT1P2QZiLN9FQPvNs zd1@wv-z3YQpu)5aP=djcNyaB<=;ra$#VEa4YHe2ZlS8Co^wa{F?r_9yfZ1v z1?aNu_%iSKDumKN%6Y*V%JYebR({d*^|uvTCA1o(Ku{DYhzNNZp(G6qO`;14N+8RY zS_z-;&o5Z15GX9mKq|%Qz5&K2rdiR|PJ1>-V_gl`T)KtLYgh5e&i(w`{SUM2;4xl* z?d5c}wJSB{{b*8Q@>KW5TO%W9c}b zTCrjU7hilasZ@%=!C~xDp$we)3c~qr3rZ|{Oe&NoQHClj4jhzH$O<=lk&s_0fcF3k zMZKA!Dv&3u;*2Ci6tf<+ai8)i|EMn?gyn0Pmstx{4uk4U&L){jrf6-dXIWP(&Gof3 z*4FZYJ8tIm`9U7pd4Mnc%lFv2el^!$xgFbeuyn!oS6ob2YZGTL43f#_5gJ5-!G+pn z1WHMS5d_Von3*w`fd6YWwr<_}ca~-S&YCrA*t&HqlarI|-M62Sv2hC1qkdNfZBZTW zB6r;@{~&#!Nfc5jP##h$zhJ$>iC(Os{GG?c&l^~p$Fiz9Ub9uO^OVk0M?IoZo%)2f zsOI1u0YSywyF^))Q(Xl8ZKtsL(g;K4_Cari6W zGN)Gy{dAsLjP6w)@X8!W$#U}>HQ$Tp1!8^vjwTioX`)PjQdwADpXbW80Zv}s#J3;H zbNEb&#%e(*=sVg^3xh8D`^trBx`yp}oa`H9cx;LlJ?*UQ?x40R&e~<2tXmRL9(L;4P}VHo6!CH5aV zMgPz^Ygcu%tfP&pc$8ONvXN~YR`bYH`?&An$Juk}D6hTd3Rd=X;dwUQ?aeed)X+aX z#`&R9GRZWN>N>1gkja6}D+>6}X?wf($>Vp-7UlMpU2TMdL9AeaU^qlL93Yrz`JeW| z|FZFgPH64gwKaWxeft_48?W2GeLJnKt@QTxvVZ>plF20F7fzF&m`1l2qBa$LDFJex z!}{Qv4{w%FNU5+Jg;M2D z07*naR31R+78-uUr}DS5Z1$Cs$O=URq?AZ05kg>D7PHATkMHi~XHV?m^!Y(XMki3N z!!0*l#Yf-wb{gvH`1-%y$3J}Q9_ErMLY9AmWOsWT*X-C%TWcHXxjC?lct%hz0smRX znK9m&hz789lRzMZ6%3>60c2?gqk0v3q~rZBWHRg5ukQ&4gS{;+Et|J*-%eFk6?^yY z<K~^Q-yLdu|6I_`84nSH5-6Pbn6QR3&0`w6{`Q z6UUVbqH!{5JF-M|o@I>AvC?yO!j?lam7+Ej!VHEnyKh0OTh8bsf4TDcPGr-jO&1%6 z@lab^TYU58&6uXi&Ye5y>+1s{W=(@Fx#aBcTLv41SOAt-9KBh@xfl1;WS-iWxxJD| zl8m0Eu~z4?;|5Qh3{oGLc%DSl1i^rbsrwRR$8-Mu zyQoU|)4yn;6qP1%fq;cliWBE9aAA0qmECQuTfKtjQXO?wQ9k&NH*xGtA3u9y5C8JL zA93sJuVFTsVz7UJE!Wk7r87HY$CoVrvn6Z5eC&|TkrR^`@inGt?(OR8if`Mt4W$%MKKUeP&YZz@-F`h1*>d2(fib7VYJE}MzT(J= zMf|$5C@PB0g}_a@hfdkKRmumw;zf#PiiO>0@nf0>rIKW1IEf~}GBwVQ8O)~hNNJ;K z!lyb?p=*LjFhJM}plN=%vGRthTm-35V`E%?@kaji;~!x*o#wkg_z6=}Glaqs+(HR-kBP~`QUdGQMkGY`_>j%te`ka@ zT#=;b+z89JjnlckKzigfxsnll9-x0$AQ1S*^5x6fuwet4OorXNcQZ0Ff)L_BAP~5| zcjwL|fNtR@&EF-8;D!&S+f9ZDq|&-05}K$M+ze;LS%>njDC@bws)5JaM3 z@+F%m_VjXLXq0QNxR_j_L^7GeGA$yp1e#%yFU+AC7Gw)F)R0{Q{<93n#x_jIIwq&i z7m=kQ0+vnZ>P=XoILdaOE9iee6bgNI_3G8EUAvaCu`%}S*~9eoG`g-oaN@*?*DWS7 zy1uB`m4)uf6}f_3)I75SI8o`fDa-npN?KQxwURHQbE}@Yg_hTsCZJGo2uGqcwl!ee zGk&l~)36y+Xe-?rlC~D`YVL+%MX){lOkS)>DQJr1_{<93*BUo}2j_cug z8lJ0D$P{p<2C(y4iUn`%Ie`8%kx1l^)~#E|%9SfQckUef_wOg2PNQksw@#cm@y=g4 zh$5aIPJ~6xr50sz{qX%lt8h>GVgcg?{s%7hF)E92aZ7X01*rtBoec<0P$;;5@k$xU zC`Ga4V7o3s%OYe25lX{zCAy&zi$@9CHn~EPQpxtioaKCzzti~FBUA zf7H`Cw^E|)%vSPNY9S8#0>5sz{F!1g&ws{ZkRG(Q)e?_~$>&Na--s|c=};(m<>DFN zl4lD==CWBzwvDd&+nDFN1Wb#Xc$}(49K$eh9T(|&sG4 z`isC%S}RJPgH#H~b#bKxO=oUwlHzod)oU6?mVp0^F@Ex6Z@=xgt~gnr@EWFV-* z|C35VHkBh_*krObkgRKHtjhjvVKjPV^znu_R^Fqfr6s&_<;o}H@%T-fHf^G*sfqpj z_jBaP5lW>JhGBf*)TvXSd7io53yuwr=fB4DAS@gv#;1AwgbgAH$6SJuW$T--y!`t= z{)emE{7(uVsH>~nv2EKnB9REYcJ1QWv18b_jcJ;YQ%FT#iBi*$*bfsgr<YM-gl~3Gx=bhRs8uAhNq`K2Q5!6?`d1TWy=;k&tuoF zU7S024k=~MG|e3+PoBK@dBx0sK_UtD^uM5^91e2c~FPJnbE zAYiIc%{O+h18{d~KNi@ggHrHbV0k zfI^YZ=b1}qDVA(BO+&hpLZL(=5o67YE;g=NMtw~+#gaqGcFO)xIpnE4K;b$rxk3?7 zDs)}oI3A+9ih!jf6|rKe`00yQcAvTb``>-%%Nh8;^c(-$=l9h=_2_YKxF*3{KlV2M z>dRZ`>9qKxKYo~<6N;k~&lP{1+#Ho(QnVd;7 zJU+o}DvhpdC;})YDB3oyO?6nNNjMb5Ejn1?AQbZ$fktXumLa@BCWc3sMPjjk`Oy!) z`&Kg)`r{jJxbe_0Gec@2s{HZ*eseqWAJJ#@9pLi1={@rW%$xqLa zAD^YBDb7_lZpH}KL+U>Aqbd52<`^C*v1&^LwN*Km^|UZDGRlPu7szI_=(>JfN_kyh zU*B_XVk&-7+`O`-i)Tc4w1qm{vIyCidr3bd>N|rkQUJf)&r^Dk&qKV{BHFZ)Nb_n` zsDb482%+2{32hQn7RU+giAJOxZ~C~-gwt$zWn_eKJ&$M zoEb{dS|24IHjq+LEEJKhM@@CyzcSAwpI7LHPGfy7wY61@Pt7noK1n8L6A5^@(xaob ziMHkjY**q*h3j~fQXciir!cEa49#_7#ll!2o0;jEHyFD9hI{_)Tc6j1;(y(8%iAY@ zkxwH8+7C>-|oHSfnSn%4UImXIey+|?;jrKt6x0K`+nz2ZvXJLpuZL{fj-XN z{~3xiE|KPSjEr5N{i0Qno`6i2;R%!Ju>ne@61uKGrfJ%1&Ye3~dOiSKRI2)nqda-q zK@q>mxs?dtp_Q_7La6^IFC?hr`Bq7hNly7B_$i;A(Lpx;OvG*dGg z%iBYKF9#)YT^D7UsIqF)a|IbMhiRB}G&fTfi((gN2?P@8hDD)dmz!$|Ka6T<44fOI zINZmIo+%m{)-x`)F*@5sDLV$v6jna`k#HpPo_p@T>;H2x{_^(QZ?_luG^z~vmz28m zm&R^a*71H6ZH|Iq1gdLcE(7;}XOM4y;W5I-D4p#ZN4|SEr}hodvUUp-!xyM+ti`ax zSQCdhIw<)1eK~?=0mIP0H!v{p`q|mp=VcX&9=BM6b*AxjF<7L0Fa+f+siBvb?wYU`R998F>v zzJu?3J%T!Cm^CYEI58+0JTp$cHbJOxl3>`y4L0M7CR`_vUCdgZ=U!VIkG$*FTW>nQ zYR%@r@BX*{5xV=XZ@eVWDgC9+t*87`D9iQPcpk)K(6bsG4gU7iyZFiHzs|()1l^n0 zl26UxIUbGet(@B5iz9;ARsu>XbY1(>z`(#;p6^7z{N)dt*Iu%&G3h`mR|fVo!DSyUAzqMgTNRBDyDnUG=_Ooz)4K_GZDVw31gC!&iP`8)-Cpke(EW7P z+I-|qaY~MdE6Ya}sY>!{p`(OSeu+>6z-}2UX&&^EH+`Woou|($769gxY6E}0{i6~hWW_m8q)L0U!3{^f$(3BR(pz7f0U z)eKLD7?>_{{MZTF(tpmoKe#25YyN}3-+$=bm0LG1dz%nKzAS(*DqOv}1(es6( zOI1x3s>bm}xLZQUi*d&*4 z+r;`cD|lkh0e<$_Zicfi2^~aap`}Qr;)=yGg|bdZN>H9edTPF4<@t9RAQYxpv?-0B#yI;Z)r}#n+9ry^WAbd0$%!m(Foujap@pj;Ka3R#a%#vya~*_G zAL0A&-T*2@+iB{b}*dVK~HxR zeY+YsKikd9m2svfCvN}FcMg6Sn0Bl{l=Y!_CWNS8T*bu3T#~+!P z7{8>eqn&snP9R|7xG+}iM6I}tx$(oqm?ThBLv_q#Mzxcqfq>>>DjTFrq2LgRMlq34 zDx%yHdD}tL3`|W!L!zXM<7tEf8cJ#uZH0?gmRpp;T`8!+L!hCfl}i>Wt2QfoY31)U z(gRIZPD(-34R9Tbvr{NLK*x^P;?{I>?nhszE0V-gDU6^_F}j_Ut@zoGzQ^^~UdFpV z`PV2f$btRG8J`#}=AX)E$LwIHBt-wEUEocVF=kuI8dx6IK zTHg2eTbQ_h2aiAWAbX!Wh^dtqfLNr=l$vktmGb=+Svl5|rwQ7Am61-Ty=*3Z$=uu= zV`JlN+PHxY8!uvXWCWoZL{`3vT%v=i!Tp3s$Ec16SRFSQOlFxW263c8I8lvMic%qm zBMb~HieU!P+ybs=lP^l2$^f<}DU|%(ARG`VP0W8UvJ76Ix`8HqiGp93;5V!CYY_wv z-l9TyRc<$=u(LBD(|Cau3{4iW2OlSqImJ7#H0bQ8rc~99U4K0z(aX8?$_(Azr?~%t z$N2uYzd=`5H@SS4U?AuQ47`^Q@Z~~FzKZy2ew!^PY9>c#c-57g@LZ3fGyRx`L1SAB zRw#&)g( znV`HQEL3n+q}oCVa@h>160X_K-u^A@JupIK=qWau=jd2fB+#{tT-9Y{LsyZ>gkf@+ znnZxk&K@q_n&PKFe+r>##A7j}r|hD#OD`MXdyA4mQk5xzw!ojA5=0US5>-_k+II@u zwyAGvq_(Nf2bYwj`~TykRz0su8yPsC%w_AV+Sgr1=-e=~gNLwlDJ(PSTPW!}fc_UQ zKxycvz|eGNrpHOn&Cs=SEz4K0;pE|7_CNVBLw)1KB0yBlpG+d9!t-R=Qa(S;j_o)_ zr63#*lP?tLJ#vI&r_Rz)-^kjF)>0h~P%7mJE?-YR+fC~HA?(SM#H>-eBUQ|JC1&j? zMzogtNQ``XhV;w~P9cYDg(wlDgiVzwAw8El+oP%~j4&0sqAVBDEIRt3+$Y7CUu*N- znuS;hb5#oA3;8_7e3s_U6|A}O?Tkx@zHdBAdubmRueE90wuWTvGWzCLP?XCFx;d&s za}~$vnXc|`q!hTGi>86D z)B-0L3Z#Y<0^KmsHI32X0fK=LYqwm^%5|GKeqc9edY>dcGeLFG!>rQ%aGvA&;C~)e z2SC@*vV{^x`Gk>ZG(w@^a^lo!X6KT0b#|~~#d4y$Agj9s*Ivq8eHY38LufOD)I_o* zB2`Ql^JGO0(b{&xkvPfe3G(SQHZWrbC`f}U!zNcOQY8e@s6jSo&!z#VQ0w zNuQT$Lf|2Ns;Fs{az$n)Cs@968SAgSiI$Fb0&^$O1|Q?9wkf(dw~|S0p+Edu<_fDR zITO^^KrUHiY+{zNi3$4qhl$1$R99CsI5dnzFqU!2j`bgXS%ovDc*ZH0qMY$6-!}u0 zoK7({mPH6bT}va?4RyGV&A{pNq$Vebw8wy7ZVXZ>P$4&H>KdAo%%rnCb>J-Ha|PC~ z>ZUp#$M!s=0z)d4CXqt;6;$P&NCOO02PGLBxIiErWz+x9-FpVvb*A^7zmw0oId#tH zMkYXlU;yI`IUI5#Cux*NBgt~Dy>{7K-r7{PE{~k;@>Z?A+I8)^v|5j)-BH*H@@RrY z&TtrqAc+h#LI-s2d%JJG_uP};{cvsr&C$rB_M3q!5EpC|aB=az&-p*k^AArv&&e|% zV&~R-Y+d*!-CC2tvk?Jzq0ax0Z^=YLio%Fq&mjzbR8>OLEV7vl-LB2$D_5!28yq=w z5KWV@)DU@~L?Ay#r!qpLb_=aiW+>GnXFAk^9IlzAIF=-pt~!(`0Nt>__pp73R?la>vdMsRn~xv& z&%bg{9elCRD`vmiY2Vzu(dg2%4HBsoqtjzZB4T}Una$g43=AY0n3@50{*r^g+I)7b z^rttQ`X`!>$xt#uw`+6l#%;>wD)${e!0gO8hG7r}eOG}{LYBim?_5Smv4TmKK{iyv zz-4=F8Qn@Ua^e|E(&BiWfB88bua`5p_(rCJd zdXMqZfYJjG)0_GXtIgv`y+H{gD=AOPjdQC(f4!U1w>KE*nufB`4r377gCkk4aT8V%hbnSP8`Wt`sDb=;k0EUku|9H13t z36%l#^dRHOEUj9Z>TZR=bwD-H6z*XBy-FY5DMk{Jh-g-;D2mGC&wiZYxsya2uVI#7 z$GZ9|ho&6{pE!(Dc!C}ML%7ailF1&jSLXK34VIRd*x1-WQB@4XB4L?GNcf&dNPv+{ zQ!1uV+ciG(WXSO+k5O&^=Vv(kmoDq?IE3x_QSSSiBtft1P#lJ(n<4=-M`lqM&Lj%|??-wZ?if&BF2}6OV#nq`#?-B$nw$>UE3v* z&S02UOy&~`iVW>W9oBQ^ zhaceBqyGh!=D%li#qs~jpPVES_yJ)k;kf~R5R$M=a=8p!+q?KdNG6l+Yl$VyWRh}u zn;-1#aC?276UUA-I$UC~SU?<{!#R8k_r^<DeP3d+eheIB*bm^(>v2|98g3GTW(RNYjr{FCJmDc?5Y` zCX-#K(W$Vwvc}@=W!jxCiDa5oN+$??Jhz|Z9tkX6BVWwpdji+>h!mAtxlH!KA@Y+G z)a%Z@ckqSyi7W}5qX))Nbq&w%k;r|pyn#Ir9I4NlZ}nvE z8?*U4pG|Q5=coDQUq8gZ{q0Tu;H!&VTduQP?Xj^{;lRWg51cqmI+LMJk@w!a$s=>; zIQsmTXx9&u6J=ycaPjgLE?vBW>-l8T7VFEGh&aaN!=EQPxX|Io*$@1oi7>4`1if)oUO_u}~yoC0SZr;Kuc96bmJe9X-aG zhwn$$4H~1*pe3f5t)C^geud>$8OI8#xB*qKh)7OTnmqm95&!@o07*naRLs$-ZLqst z!L7HD{2pWD<2?20Uu0r>4tMoD-BvQV`~S~)JbQv5P=^CD3Tyy0MS4$zZyiy7>0_F6zpCP&*@>A7Lf{)2*~6!VCcxQ zcW)j1JF|OfKkm8vQc)n6OR~1K#%`sGB0*_nkX$K`({a&sHFo3uK=po4t`|FoSqbpG zkbn4(*O~jHI{)ogPV<}p^lARq-#x{@{LS-x>;JvR%1Q&*^(a>=)O?-d>;sHtQ&?J$ zp`j6m4?oJ4m;M89efR5h13@~Gz%VTYf@DHvZSe|rX^K9$`*O(_W@V;ndzi(Pt@n`!c%78kB0Z$Bi^=V-N;Nu4q&|%%TDYw$9XDiZ z_Bdk+7yqsQg+${92M;BfICF}sejnGjX6U*>h_D1d>(q9}b7!U4x z8n-rFG$~?eIL*QPX8HZEE%2jnFA`RFc;dxrp8w>B`S^<`SljeizEMU|W!85ZEZn?K zCZA^Ru`gqHWH#2WbM@SNbavLsWOB%|+~@1Wx7W}$+N}m#o13$L^Orw&{F{IF`X7Fv zab`04w__@RMdNN9Vg(EqeQ&SR0#v-O?#>tPL zq%eGdf*z3C`VrRZcbOaLaNmayq8)vT1^030*AG(JYN2$mGcSirA69Z2g^!f zXd0TTp=nyY1&%^=T|?ImT8##}rjSZmgaRa01!Pp!pfEU$=roueY%_EE7@cbEjeqgK zz53EUbMQy9u@Gf%-7m@UcO_op5D3U60!E4wVJJ9oc#32yfhbEb@q|nyYgD#337jUf93d2gu-C?Kl#vxRo^(t5;&()Zu4{C=Hszh&<6rvRM`yqL z>bu|g01f}&tkZjy)3 zoZ;lLLueA*y0wVwIg|={EXyJif~BP;u3o){V|SSy8(?I70%hVMR@-S-mN)3Et)e+~ zis}l^&H}B4b7XekWG1!Ap$CT04n06Q@gXj(9biBpN=4}TGInZ~-~ZQdld`We|4Kl*P(T7y5z=vd3{$7w>2Y(VMxoxsv^P*x z?T*th$bHL^zVT`VrfK3h4wtUp`qDrDuYY~)(e&gC&wS-8!56>yMdc6w@DKky`6`Ok zXP$e3#~y#2q7|@v>uq+n*2!kGeDp)Z?5?#~U)$jLu{5n_3*j%~tl8Y$nIbzl&6j`W z*Ld{d)4cN5SjoX8!zjOv_~E@HGAhCx_ab)7tK?@lmaOvhy=NmNmh?oui0$w)Oq5*ExPq4o)co|=DxqgUZ*blu4)lNk}ymI&-1vs zxbm!aTtE8(l1imXr?T8$ zTj%D|B9ARR%%?u}NoFQW$mZwS9XiC#tKY+3UF68A5jsN;u;ScLWg){zQRTivX)4tQ z*KgdST5D3R)fvdED5{1eMFf6`qRBB&Ns^HzfovF9mWgR&gP2 z>vQn<9IC1iMjvdPxfg$PH^fH}-Q`~qN>Io`eYL?3prJyMee-jr830+fh{g4Y6uAS=5*+2R>U-_jM z{?1o^uLbbm{Jp>T1=Xj&m0;aqZeX+uLOd`2zV|j-F%l##=vT z`SuDApFYhKkDX@n@iQzAjnP=W$PL4!wmXgR0)}%gf$MT>bBEij>-2gq$#jOKl|Yv2 z1W|~h>X@2I7(p00cwva48>p&`sma*3jpK%BnuZ_PY;LY`@zP~h*H)MqpSY7N;PiYD zA;r;Q2z|U>?;fl8`wM)(%FFwH?)xw_oTpgI(&~8JzOhQJ(%`_c8M37uUav=cXXk^x zlYNgC>8=yh9oj@BVquJCfTAjWi|jq&v>*}@jb6mC0?$1%hB-J!yK@oxOw34<`w`@Q zYwi9sB|<{#XpZ?ibzVc6+PV_$~Ozks`?VFTWub>1D$yAb3 z$zwFTPAMly=SyVrCDPeES|W#*NTF#4vZA4?2I-PTVKks!b;&qA#$}6*4xGKwB#07x z^dleT)cq%T?e(|0csws7bcv5V^AyLAAHy4ZAtsHf9%e$L z(Q2@;bem4sC6mfv6_T+ztsA>a$g+YY%jkwiyX_#th;+h2H*`GTr_<{Z1OgF-Y;BfV zU0ucPIUqqMlSNfk1kmfn7e+S?I<*Z#+r~_1?>(sV7hQn8`C~F=py?`Ww^!L(t1vKJ zWMp!XC<@tL+on_dV9w!t{y5^U3C{c6$@)3X@kNj%?kvgoC7(!=z>C1q)3j_a0 zJ@WYssceyCDvf2OF%oGEBY~#q$g+x}>L|KFC>f|)j`WC6)ZWEzZ8KLWQ9PCB@|wfV z%_@ql^ZCzwn&U?f^XA#NnZI!pMNt?TERjg2SXo))|NNcb-!)i+N~y)opPK{ zAS;ZGjU$)0sa5MB$tbDqM%s&9jH13wu+N{2Qpib}l(vIiU1B&l!N|ZEb7KK-UEN}N zV~3H+DSl>rj7yg;^2(21qr9_2E}LVZRK)dsE?vID+S)2#`234_K}5S_V;TvBi12+M zRgTARx|Kxr0)#IxOat9B2qOo%&uMD4+c=&_x7VdvZ_w$qkrkPdkr8xNC7DRFv%5i|LA~B#Wzi-G0;Xrj7#J$Bw!F#a>Nct( zkxFL(`-9%CzPLT&r+J*+c>vsjCi@-^edr?rf#=h$HF0}ABw34-%!SnF^51ozk!0x( z#uw7QJf8>@RioFlS-EkQbSjA>B(7aw;IUIlQmTonB+&E(rj^3bEi_F>R+YQAl&H^W z6-ZG4p$A?UqyT|}Bo|2xNZh*k3Xw=MHvTXldmzn?^$zoufOxI;tbsCL2cBg}?Yvc>|51t${_akbMoFbm%rY@E&dyeq_2mtsAR<%9F>+uG*#2P6EkD%&EzY;%C!kIL z3nJPJbc+wZrmM6nRf-2Pn5h)?S_ebb`dZ1oJX|>zYeYZYoJRm*5Mt;u>0A~|QMj>M z4Cdz*ABg=w0kk|`uf#`ir! zSs-K;MONt8U367JCBQT^q+WdKRaGSn0vy++T;8PJY@w+tnM@Wvl|zwLkRg@O@LdN@ zi+cjlQ!uk%^2dyY8)=z zj}s;68`Oq^NQs>fP&1$=LDmqVjU)^n`|KBSZeQc(rI&H#S^mQ}8k{(=#`DjAf`#oa zLYZWH*XF*XhZr9n;m7a1%a7lFn|i&~kMa@7QcNDxbPeD4(G`hoHbXLdi^?K6w+!nahx8C47z5ZDk`R7BFhrZMw3>vMZuJ5H0s=#Uq=eM z)uq;Av zm$20#kxAcU2Y+9DCO;WsEXTCubT-BCNQwDtE7%@}I6Gupw^6XaH7>eG90E`4T9fOm>#YCTI*)I*dFtVi ziRnpD4FV^?N~##Tfz#{7W=@)q5_FK#!w`6sFMo%ni?8E&7NzOWk}V#wx3zmsW*9-Cm}Y0Y&TgfSuFE7-7K3Ahc)lOQ zoDU%6e({(8#@}vU|NhUY(QYgW9U;uVMmCBd@I}8DjUbYU`ZvRF^%yxg$&n`? zr1#Zt;Rmr#=AIT+k@p&k5TsbFzV{}jelsBi_^w0Bu=s0#_kZBZrE`4$557w6`c0eUt~0qIl{yX}*=ERdkO@H(qE z&QhR%vxR z{bo0VETmXGkBsZ~Fbo6NaarHoVr^}m+2cBe;uNWFo_rz8(IJV`vnIm@6Wf!icYKN? zqonhB%9}g<@$Y_vZ9B=>_(3+-77>z!>v&Xmswj#?;QRPJn^Yl(l+UvB?zMaK;Qyo% z!5*K(G+=wH!N!1%swv2d%;?l`oaXHWNRr?`1@V977k}}Yt#bJvuP@9$KIHrHoLJ(n zJ6I&{QW^Gbks~1pf*6uWGX0PTISxWLBqonev9q#4yV?THB8(!GzJYxxWMmP$DBlT* zkfgp{-<~c&AjuM)b_?54`25fR8mCS_%y+;32fX*%cSsv$cS)VrYa`yUV$^-sQr(7wENW zjGcIzR5C>vgorT2b?lgaVwj{;I?2HtW~xVLWfiC0y|)g&{1+^<_KKt;L#N~6`6^Km zGBPzpGG*cR+&k2O=%+xPFMa7tgRN%$H+O0~e?!)F)X)IuE}cM#yTpa)?u2ol#ut1y zA_^p=e%iO_&o|A4#mc2ylq+pyO~n_2u&=|F`);feax66OJ7n#J8_4?`TcM!fV1@JS z)W$H!eZ%io>J$euNv;d9dV? z)Yu+??Ow(T4}P|M+3%w;h^61J`v3e4jAzNhFhG zaw$SZ##404OE;K1GQ`;NgZE&?-{-RMz5&nP|CeQ4*QYd)r8Jbob^JTehfu(9w)ejK z^YM>A|4ZvDOTXm{CFctRO>#*46_T_GCF2eSLE5vqBZgYCbXW5m1Om^CMZi)&y-*OR zf%|^Q(&Z%%J#`xEja53^Z30D)8&*J4KKWChPt8EC)6n76~# z_8BU>BOJZ|NsgVkpI2Z0KCgcFkEoo#%;Cca2*ZF(GRbpKJ<3M8!aEliXuiG4-1rrQ zmBSVjq;jLQI{{&|OE#OL=L;6zyU6*s-=Xcvl#V@5cKm*l35(&pMR{|L^A|2s*{xz4 z2DwZMKk!MU5*VtE9|(k`AR>XPNn|ovLO(!J6bhvwMoTHOVFg2pNSOks=OODBQ*+a# zGC8haxxpK+yho*6=h4$yj?Iqo##`H%s)}kB=yp3ua_rS9Niv41)9KjMI!&n7QATxg z6C*5MxOHzr9e%=wdvB^EOW^bZG$X;-)L@LKLqR4HkkA|)AHu*a13dcFXO0b~oqy8q z_CDK-bYxjWvp30v6|#vCRhJ3-GxR;k(VqsQh`X;55JUpckNUBl{jp{ge|Kz``<{Lf zYoI`F>m0ITLKs(lgoF|gP6_*@BSi=lDPCZO(Oo)(ED5@i#>#S=!=)c{SiQxja+SYFo zibMi#-nz||ix*=YKl?C~vky}onZ%R>dYvX0E-rKR+B}{gkV&OTBrL3iMM_EHx(*%B zBa_RMPHLEABXqhpeh`2pVJ5REUXurM9;J-VUOK)@S@;Z}~ zNq*^bB~G0*kPeJ8J~zYn{&=3jg9=$AHpDdy9Z6QG)oOTNgq+CXc|N(p0*$pz63OH} zI?ntFzRsSOBQBB>V-o}Y1&7B-#^!b{%a1qi=ea{`ygP5tKK!Ad{rf4o{10ng1;xmd zcB`a%i=>n$M$W><#HqLL>;|~wX)o?9tHOS-5cZ)?5JZSjAS3RCHb{I-U}ky{Gg)9~ zx5@ItO?Gx0ln$KY;Qc4C@*@-rS?uO6*Or&qD3`HqhfF4oVd!X@h9m@@??NC$C@>5a zLx(VmXm@Rz%@&Fr^Xp5cJev!b`9Cgh@Wi7>7#PelJ3B+CYxB}eZ*k+sCJ9U7!)Gi$ z^q5Zm)GYK8EWC1#-NhQkLW!Q^5oiIC06z=~qlhpR7^aS5=%@*kjhpkFc`)jG{XW1tEc~$as!VtJY%X;rl>d zB?>~KNQp7M5J+J}C`%|xgcSBKj4I!8W7`{YhGB%6&=I*A{^Z+NxH4bnnP-o4Xnciy z_jgDXk5W%O!p(&_X778PN1u9{m%j7I{OLFTZ#FJmWM*QF@BP3bldUr|Gm2*DEG;gv zxxPkE%8?j*lF?JoGCnazZEKB%`75k#tP_a<)6hvJlgN@ngp40V=yKff_@PfGlSWl_ zTFox5=VNy}L{WrgnSH*Jj$v9{-mtm;^>h4}UwVQoR~C5XM`sxmIWenKiZ!{iETbDLvKG5*6vxL%4is6tvT%<=ouAwu z?Zf-AP+3q&`~2`~ia%O>g4*(B4tifjFP_0HJk3!tHl{UNE zE$Y63mDf@3JWAeAPY@zL{PJG4kHB|hPZ=RecZDml={qCSLsZtvw3{7J^*Amk+&2Y^ z1d$Zek>!5uXSBBqApV0y6ybI|oca8(a^%T%UjChb$8Y_ct32{phWn0`7%sfVz|1w$ zrN@!7M5stTa*Th=voS0*9jwNwb}?Fp=%0$5X7MmvO>My>6_k$guaiet5~T7nyO*< zddRW@NTdz$1$aTgt;Ka*PodtZlb&kw#G@zKsOc=c`7X_^RjRE3j6n{}B=ELeP(jyq zbX`YLRAf1Jsgp#6q)14*j;cu5J5^*&zjvEk_S2I0hc5K}*-b-dW!vH08{g-?xjgOs z$5^No7#=gRiU+CMt2mn-wA46yN~g2hU~{cYSIMv~XDCKp6rwu@wR=%Ft__J)zp3qC zf*=Ifk1@T}Up_@qJOWiTjm1k#el4QxRcIN>lo4tiDlxB!f(Z zBw}~8+D;kC>v8J&FQ8^eIRDaj_|D63@Ya@&*h1DqgpTsz?0% zul+S1`|xx8+kgH)^3Ll&qEIa2n4=6Idz|qDhfoRWwp(1kvCi$=OXPA%CMG9nwK}w# zO$x;Ve&C=e5~);%FbwE+TohHsbA9ZtOEO_%SUQ0!lgy;>gRoChQ*fn#FcO6Essh&y zIdC+~fr%u)^*cY}r8nx>B7@g$qDm5@BYDh>pjO$Xx+CyIBd+qq6E9QOkmY#6C(8Yb|d|pCE*CJ|_EmrjwCr+KFG=7{Ya=HA@Yt+h3 zQtCLx$_~XS!&oUvJ+N5Zvgr6SrqsmjF9?Jr2*Qw*AyXX8Q!Y39o{%xr2|_{O_ieuS zxD)*qbI*3klyVGC4B~XJ5fRa!;zJk{*<@KliXw!p+-YKj=ue4cg)j^$Z*7su<{26t z1*eUY8DRLK5A&?jW{Ne6+Ah{W7VW^7*$}4*10TcENGA<$UB8Cw3y$9ZAkEdQC=*XI zG&INf=m4_UWp#ang~eq;BxYx)uuOyMZWGt@FcJxRy&g$R14YGl9Fhr(bhd!wI3z3s z(=gFhg&_3Nm6)H?>Db6h%o~rwD9*f+#KeGJi!`0$wsThdI2S#8d5(GiO?ZsPYBBax9#IC(Q1cg&XK^3R9LQ!jR zay&yW74Y7M#Enjxjb4ZB>CmRFc_ar|^%QrdTYY zN&(xOYpkrU(QdcM=kp8<4gdj_N*zClFf9v3QILc{R&{zk7vJ|WjQDlndL)ubtW*NK z*`(+8FcL|69lH;MB*Ne>(QohH%hV-y+pvCR6CnlUG7tu^wAf&Hz@yr<$mDahx31C& z3V5yyZVx@LlgT9U10T=zP&JLN?a=cS(%Bs4#YJ@5WQX$iDAbYe!koQ0nY|A+3) zGdg7v5``*~B9QwYJF+62$ zN!;Rxi3%UZ@e+v6b+QScn>W|Ec<~~;^*T``$YwI6Qz`riT)WBj+qWr~%Ve?{rl+S- zHI1Irqt$2;g>jTm82Cho@XI|#GMjdG2Y6p%Jxw*k+5>L^~T%l76x=AhnxZ=zqdK}ZT$-oDAe+yqwI!mjlY zB8sKv(q0oB!yjd@%2z7*p2w3P{RAKXxnIK$HD3Dq@51V<9A|-(rwv9PeU6Iy2)p+E ztle&7tiH#=Lo;|@mp9&clhxHVBuSx=E8zP+j^okobSdvv*)DHk=o%9fu|VGQeQevt z?skcUgrTcwszTt0bZnb}WP()M!b+GV5=pw9F1l_YL`1LWqDY{d7R`2mEXR#!h#-mt zre)A-cPI@_Fn{${EDux_JkMvh+GKWWn5Bx%pPno8Gp0??3kf3yyRH$L>6It(yOlPHX+H(J;|heAHj@X#Q6Q^pt^!jFd7s;*P7uaOqp zOeZbsN{*(HrP<3OnK^<^l}4|PVTN3O<01)DXJ}5r(Dp4F`h4k5$7NuAfa4DzB>39q zog7%C2%$)Qae2I`iq%Ig=8hca*-!rrrNZ@%scB4TQ z2C)J`Qettth;VEN!_XNYA0nAb({mhpwnw|`U>XJ@5VYHE!oVk8$fGC%Sy7Q?BYxh6 z0YZc%6FHpT8bjmb+<)dV-hAsVy0$~cvhad{TC>B`_m6RT!DO*gXA+%WRKP49AUQmZ zoE|`g5ni{69|ml0ZPB%D#>Xenbsf_(;thHfF*GxdRxD6o-oE!RzSJLjDAN0NA(8-9 zflkN4?t*C<94vX9);C$~rU+9*^nwsoR$|4Lrp4^SN`+>#$@J6|vs04AGZ2$<6uO-*%|?}}=@~x$gidGpo9ymp9X9w4HIe&eVR=YR*Xu5{uI$XSbnM$R?v13QcWinKq zh|=+AFrAZR%kMDMUSzqp&AQu0w+gtaLAr??Eu&1cSLU1VhHSJYG+9EH1tN%Vsj8_g zU0p{`Sm=g^??(N`PbTm^%DbBk4i53fFaLG!f9hlSp~~f#zJ{{?3N!jL6HjK4CqKe! z?rD}cCWwSdG1EiM7;J5odH39T$~!w)rp3_EAfX>3$qJ^f<9i;tTplZ#h;_QIOS!yD zrMiw3`J@sCiW*mX2^r6GQB{djDUV_4G@IRcMlV7%T|rf3yf7dV0!@*Lq7WmICI}-O zH$+!;!oWlBvrBc|pj@snIyQoB_t@Uv=7G}>F;i-?@a7_K-mLMQ8ev){%HSk}hfiP? zC*z!~(8Kq8v|24(*QGQt$jCsEfuTXBXQp`V^*3lVniLB~G{eM0qStI8s|t~GkGUm_ z{q(Z1Pw?7n8rwEXm_g&jwdLTGN`pKBJxr6c&_HUE|G|^3gaf%5=B)E1Ru|Zcder?kMtTq{F-5OiKgO&*O3*KQnAoaPYjV1@O>ZCG#MHiBv&Z)H@^X4 z6cR-NVc=3I7BF-J-wO~z;5iP-lu2p0L=c2jcN^F}H>PG2r;tNToD*S$tZDRI4>K7e zBItE{7^aEm`9x9dd#NZ2zVEYB*=2lelpD7esn%+Ug3O0M@*$d1fk5jre(WgOu|vqJ zM&#NAzK`SkxV;|fWRlV0Au`!CimI}?U1oY}5=~RNdi6TpP8X5Xkt78xo5r)`hjHt%jw_XolC$&8L0p_@9z!7PglRRT|-n;M}a_v3g}!Z3)lX;rmPX^s~}nREu% zb68wlqOwzAWO#_VnHdJsS#GuR2I1szT07X? zHeRG4bcra87?~=e8!Da~P_ORNQzMR_e1H#s@(Ub%;0emNF0=L4zhES~#^E_A96n0b zI?cTIFpb4Ly1Yg)r&6yrxN`L>Ya5#cQG{hBFboqB1jwpR6huUUi!3W>s!Af6V!K?X z*J+Z;WH3`1a=8MAt`SBOvZ9mDnAEFva>W#>T#;(6j@{`J1Od9C$8c%yLsnzvXcz>j zT8dOMfv&2Akst_s5J6mxqNtzIBojpucF#fYcA1=*;PRC#v^!nW8JRPWK0+pK#bFY5 z8zDlvb`OL^E|+Cucz}F9hwFIA5@@PM!Z2A}TBgg^1JPL7_C5XJ@BDr`1E(K{r%vV%IG*8CN1Csjt?T_wBzT3|+_2 z4P4jZ*1{s2TV;+Oo?~uyj#QyYFLNBDbc}-wFH=~(0!azm*k!YmV5>Jkq!-YW+jO_K zXf`@X#aIVyx7zG%tur-qm>0kJ^UR)njPC9_7k~esVN~AcfeDA1hh|~o442EZEH9Lh zg-1TQMkq(T_wFVaE?huT6oy7e@VyvvAR=T%jW?T;L^7R;eK&oVPPqpnLP4R`a%kE< zrmA8kGql?s{16JcB*~ zE|r}sr%&C_FcHzI9)Mz37pK(@y5kB=fxo?_X40H^r?kt`U_ZSwzd_ny&~Uge$V zZ@>FZC!cd;-3qE)B~__PDoG`QkdOh3AP~XWR=c6W0gsz$+hBWomhEX9do{MFJv|t^ z9lFPEyW4=tnBWEpfrL;fq*ACLsiG>~9M3)ZO?&V8u-|)CczUh*Ontmz-E;1FcX*!v z^AA}Pv)pWQ=JaVUPfk*;Rv4cc$0$XXCMXSI;Nkn;dZQCZF};32$IxA*>w+v`vJ{=9 zWEfQD<_u7W)pnag7@{*x((6;I)IbVEW=k5S)Ve6fC=Ehdd|zb<$3?4Toq}zQMoWVy zB}o<&$06MUDzJLp zgyw3GM$IKn?Tzb7+wc~`0)mJrPVl6}5%wx}T#3@!W-I|}4QEGCC>C*Dk4uwN%*@WQ z|N6b$a$7>N+Mqjnh;DTk3yaS){^BuqZESM=F2R)~p%vV~rF}ok<&FEeBs1oc*Rge9 zh1sV*k30PY8~sJL?XNR_>s`#dH*xyXE*6$FL#4B9-8@1sjW~7YET>MNM`bbFcWk3r zEVI14j8U3KqiPwDr4mV;(C0}QkEm*2LjLcaAiQ8Bn+a2a#*0BDiWR2 zT508U;{dHP9O2jm?x;%g4MdlV3II#al_Uzt)SFh8rzm;>7 zTbVrnI9o29WXFywmD*Vf!FDRIyM?DO33%`+wx%zzSF?72YU^DNXE$1xkrC2l^j zpET(*v2g?aPMcI28beh^8Ue&A89)^S}Atu(@<^agf9EJ-PqhET;K zwGqwg>;kQYg=?_X5myOP%)0Z(tHZ3T5=OMLo*=I4ptWHz7%)^RlPM3CrX+ES>&hHk zx6$Gv=h~>;k-_&oWWjR43qeR2gv`z_u-trt>6sZ0?BCD$#0YU?Gfnq?oaj8=%g<8E zCfR!+qvB2z^fDwXY}%MHykjfoy4#rdZ)3i-k(K5wyS5lqra5=!9B0p-Csi4K7*KLO z0@uOw90pMj&kGsfFix-Ar@7psR4vl$M`TLl`#!EKSzcP?=(EqUu&}@_x7@mpo77pLXsKcxQ!!iv+6kD2#x0jd1$l-;n8Tl{>r$yzkkYrHM3Rsu39jpsq>3;MkitQ@K7Ogh;+1pgcrV)y?7KGEnTS`RO=H&c z*?tJuj}wI-c!Z&)2spwa8YD!6h(ZuBP#Ibn(j>(Xyxb>K<>*iztd+x~o)?g&slBqL zL%mib%Q9Yk`DHF$zQXR^yEw3a4>#?*fy6(^?716QKK~u!lV{jC++w2-m5l+}*d8vH z?jntEp*!DZxV*wp)o|gJ%Urs2iN&Qw94}yeY?L7IX|-A;%AnH$j$c4jLRzaW7Ux$e zmO_eUn<(N30dX92W%4qeR@-jULXkDUOk*^e(xh2}YgNN!Dx*;J^9EJWZgtRF6UBXk zf;D3e3I(!Ep^Zl1pt8))CU7mRAT0XQ?Q~F?wG$~7100~$?2;)(rcy%R$MqZ%l_DJn z&yxtx=j6+$xq07CHcdK*L!v7(=?yF37#8vU1aiXY{Jw`W<q z2^`^|vIJoqgmy@x1jn&Gi=z}mJGhQyesPwSHWJu|eYJ=+s6e${0M) zr#@7t+v!;{p_GJv07BF0bZ}h<&nsb!U@(Z#S%L&IV<=ZD_(6d*jmfm3*Xdw%h8GkF z3I$wQz$+D4o|$6MY|;1;)Z9A%zlXhem9%57vhiCx`IFSJdCLgJV!(y7Gj_4(4-v=G zWD#P$j#Vn9Kd>I{rIO|DM{$hEe>ck%Nsi^2+Ix5oH<9mR-;%bkPi9`dTq2;6beOj zmN4jb@+-fFkS+%6DPIUek~m^|Zknm7X|&Rej*K!iJj_s|L9JRN@I6YUkTlJR1__>Y zm>3^r!^9@iBx7!JirL947{|j83#gpEO0ES^O5u2R`kbaIDzlqos9qxse2yGB!aw}O zXE}EK1g>nAYE+eB=F1#{FuNUL{_6D#A=VId?e1Plf-j-xET zFQpyV8*8_%a*?w!Af?1XV1)gd>qWv1i)U_vM5Ecl0kCo;Mi}Q0N8mf(9 zDy0&c7Szf<vHWlr_<(7%N=Y8sWRv^iKYT39y8G7Cu;N(5oR%P+k| zu~cNkh7Blfm2Q>cDinOCo_p~c!|}yc9DL{hvk$<4=SgO!m+5sogn@@4MJcO>vf_}O zS(s1#?C?_)X9}&gb@wfJcKojmo@40@NzQh3^2K0`Axmwnjc}|)aP9krLV<3t&kug^ z1D02sy!WRbU}ZVu{JCWcr7}qz4(^+gP%uLVX7=t4Pt<@FE z^&vzYlMWKxp(>siU`z{bAS@P%27L-)K(#W=)bun*k3P$pb7ui46$(gCl4fdskfODs zTq@JlBmP<3#aI;wyw<@U;OhGpKk^!VbD)l zUg}V(Ncxe^Ratqgq?9&jS-(nYHpUVyQ$JT8|njob^V!A0-%Vqb*(E zCmO``IxF=1eNyAo7~a4gdmG%jtH@B%P^r~<%Z}|l^z1y}ex{4-LY&4Jozd@iX}7yp z{iHRnBPkS1MDc(uO>H^i1SlYl2V_c-BpHQ*&)C=~%PT8<`{9Rq@x>QOvW!CD6uxceCjFQ_{KK?f+UHpm>zrkW|?Bp?;*4zQwd?QKHWSY<4&B*db`n2b33>`{(B`#ha) zm%#U_Rm!$x)Oy|G(EiVkHO$p{BMj84RZgEd%h1pew;#TprRA6;Q&egpgFz3iG_`7p z5iRkhJ%zfxm<+20Fvg|=R4QdunsNEk1)e{7n#q|ZM(QORjT%Bok~qZ=12CFFt4)2^ z2-h9hO{WuIqc#3NQ>Lud`DPu%&nTCDCbo^?`BOG^FAoeu2rHhJ66s1p84yJYA}3gB zO#VxWvP$-bbwl^@srV`o-u}hMql#2zDG@~7-lmkfPm}Wm=xjl=B zSMhw;`n(&1>v<$u!a&6s;}CcOtIa0M%Zn&&C^a@PF*?MpTYc`>6*4kZMpnj%l8kdF z&v5#s7YY58thj@)&j_R6la@)R` z@$4mj5eDCSA zoVvWo#8}-vdu7G@jxbb)E8s~kow{)Cu`@Lw^{cSvnxn@Wx|5|ALD;)*g86yPYBOW| z7RL&|^J_xn7+Ciz{e;<6h+L<&d_SDQm8Z-*)YKk z6CsDMbJ)JYqdGQd~qx5(*}FVk-Kn44W?`zArDVXoFGKYuy+yjjq*-bMhjSuVH%S>UxE$DIINe-D zO`qUxy9Sso2RNpR$SB1R9ZOsHC2>UnKMe9Ycw4zq6vTOaV*4mpmgiZVU!^`gg6B(oKcKn1 z!im$bkVFISy=4<`yKS7C_l!{Aw4KJLZ3ykKvEl&7Ksdjmg?)xXfaAH~I$Sw(ncdfK zVE>)B0N=Z|*qP?4g)gpJ@Rpkcg;3IHIDGfvX-*uE85@xlU5(1Dq3aqAK{yV=7^E*O z>SJ=6a{iYMCiiHxFXXw7HIK?NQe!=5gb;T8E-YzCYs*&|3=~;OGt%&R{gB}9*G+KG zk8R~^7smPSH&*b5JbRO5DdVFXnY?m^OP4M(aor9kMn~CJ(@e-I#$1<)Z3k$KjWIht z%Y}27m|KVlUD&=Z=dAm-}nZlcNh8E>>qOX$5YNXYm^+dK4wYc7)L-@C{QS} z-sJZO1JXoUI5f*J2vn9)t5sQTt@8NePjcs7uP2HX;c$pb6H3Jp2ZvN8_?}O{+vBBE zr@5{sx%ZxJ9NJN1?BTkBJnAm8Is+7UehC#PSar9kX#H<=yY~ zc+W3Xxbtwv%5oc1-G*N%Ff(=ouX*N(W)L|X+#+auH6ENQ;|WD65M;{5l`e6dA{}r&k0?$7jg&UN zha9EJw8Fybdx){kn|c2EQ=C6{8BK|ys>ADE+vBzOO+XrP^1;i@ zU0k9(JVtTDZe}Mhv9i*lQVOZps|Yl45>c*Jaf~8W8Y#dH%1mtVaZX*}QUvcm47+Zr z!_e()`my&@3;$Ox|Kmq_@_fjpD{$lZ5~tdAQtdHO)1=DIJ*2eoWtL^6iKbW%DHMEM zM_?RV7AajKNfR7lH4n#Lcpiaf$1OGby@-W{HXbQiVzt7JYL$yd@QKenMP+1|gM|^E z`07&_diaGQe)9ewqqA^@=bu}^P_~m{V@uYc7_u}o#qmd;XL+uD?Fmu%XXVY>PEZDX z2~N+Y*B9&@Rfx(E-(DC(YmM(2w2_o6C9>2`0bS3})kZe zkH_;oJJy#@?oN=Pg~0J8l}d@MpP*BXGKyj;pgz`sLV=-;8*pToFtm7h635mAH4GUY zs`K2bE>E9aX5bWg>C9!MbQ!J>(NTY2;_HwsNmz@kt~RPH^=j-2UgF@535$zx_%M{V?u2v(^clR-A%63h zjxjR_ciaqrba#fUm-vOh3z%(hu}z+Ov;B09h2{`GO!Ul4L0cO}SDcR)$afm&dsO&EMn31A94tYBPJsI{f54 zhK)b|0AK!c#795&HMABu!dM50AYkg;BzyLaap=v5;bYHSTd2;}DTiyi+f;++z%U+Y zL9LQf8?Et3XPkCFq3Wh&nZ)%xD}Ig=bedADdj!61)C_BrT)qA(BDcRYdHrt$7?a`T zjh@OfJTD*!JdD;vkqtF=T^FeYI@LIiBnUic3?XQu74&*BX_^to2_r)d+|a{uCFN2` z0vtJUnfnfJ;jX*(vNCg$x8CUzghL$v&NO1;gUuUmV1Duf^KZ^PWcI2O*_W0UVz=i+Ih(mmy8*8~DOk;7v}gyBZWlie}q+8Omg69h#& zUdPbu_N=Rd>(Xs^sMISc?bGk|^Hg!MuH3>HWM1+ZUR8FfEW?!!0zs14#V)1Hhd~+2 z3GjR$QqU@+)M$Y35%v2hol7Bef?J%#c&?8z!X};rW5Xrl*zm1~PH=v9l4^AeTSiw% z2CHZp(p+jW-zrks{yKyMmo8qR+mDcLh;#!hz|K+%1)s270R+(?=JHgZ_x2+_>K@=ezx&FBi z;*{}Sb?)50f%oiOV9QS*hGZY@$9}-$kA98G)gHyd&G?~*bOhZ_k3pPLDi^tM;uVe` zIel$4w?9_~*j7;X4G8;vs;g$x%!NC!U*DV2&i(hgpPv1U@K(llEg zjL{aC&s9YB?8zfHb4N65+s%4MZ4h|AZ+#-ubiMSFu0%*Dhc-1q!Kc)y!0bHT#U(10 zB1s(C5+?}JTG>dQtNLk`8ETCh$}4m75ug{?0CyG)W&*A#=^L+f@9_7(9aL0{s``(np@B1D6!*Aq2 ze?`$K!sRABb_O1OaDm7E=r>^ULzt+;##)WvKG^1S|6-aqZ(n4-SEE=iVT6rBavc}X zmy}Dz94K&c9GB(xfZia%bxa;>n&W2L3S?yN%&-O)2n0n}aB8Z>7oW@Mp6+w;o1dZe z!WUUuHOvpjDV98hutJqAGf3Ct?1_t9I(>zmhptrxR({e)2DTL?!=6i$WsKJZ$Kz2h zMJ0xd8m(PWR+H-Fxl%#s<2o+=!NBrsH1zv1o@bj=y_R#O^*T~x6HLV(v~729cy7SXm_DjqB=H0Yw0|N(E>@5A*G!Wq*<1iSUIXBgndm1M(R*< zR=9XJBP_f0S}i6QL)djQt|yqAzCsdp2|WRBKoA5r2|d%Ksco>cG((FLx9#rn%s+mc zKl!gIZ@vYNoQCXU-{S2be3p30qqz#T3d}CUvIA)aPCuQouljX<=f8iQxf%GK54+s> z(+Bv(kG;a|uV3Q$%x)?&MYz7DZWwzLW@$nvwmOI!5wVnH!X+NG?2rqM&XeD>L7Zm; zuwL?bo?)@;^40II&~5({HyI9@gO1CP~gx#hw#ev zYwyHgD|ZGOCPK-C?~`O1qh)x7aZa{ELe(dZBBCh9b#1(Rnr5U)N}6OONosjEcTit*p0AzEA~@&B#(JC%-v30tT%%1OY4a%X9`Y zrE(diH2t2X0qYzkdNsV-o`%|J(iDao5*)?+Qjbg1imtzp`sVA1yGzV3E@Om;Mp7Qg#{gwcBe~^*4{vm(+hlX9wD=hUZs4ON)V!P2Z zNmmsJ2df+|O!0x6di><|5#_)`dnJ3)XBnO!~jB`b3FhxL}wP4UTtfl%)c! zAB;9O$wXyIUUy1Vs)(Y<`o%aRcj%HxDe3n5thU>%tTbu2+XyFDZyAkQOB>G<&Ry5F zi_EnskCRgu)>xK82wc}8jT6FZh3N7m%QJHXr4lnUb96dAOL&W7%Y9$F{sD!sjdrHd zz{09xW-+4OiJ4w;DQrH3BMmb%Q}hP|qG*8Q2GnXbgfR97(Hg%{B+D%A*C%1ybsn4F z@o)I!U!7oKU~SGFnP4hq{F{D)H~e^+EU{5X3o~s_9h)XvT;lA@%k0|%_q_$`dk+F_ zOsv>)-)=tjoAXrZ(MrnH8#S6)fw>64}@eh^}e zCW<552M8xGFY{T6vY+#6Uvt-8a6Ql3RcnnF+L|jFgHVP{YwL>V zx`bg!yVIrJZs+p>L$kTcU@%~KXvk8M*G`yRcIZflELFI!i|CqP2)@vC5m1QDP^|q*u?iAKZB|6r!+dj zrSs>Qyf{g*R6z)bYNdn_!qTQQh2vU+S~7^}B$9%j<7VcVyFA4A&MQ7}5JC?w9POZH z{|`3ot6`FqVi_Je4XaBLcfT^l9Ur=Zzx%60eEfG`;KfU@yT3wm`MYG7jv=!aJ8y>1 z{o*Cw^QryJEE(?J+~&5;efDhjS!zj+o?PPWxfPa|HN6Re7npSyyJ*lSa5TOj;<=u^ z`PS0n$@?l7mO2{YWO$xKG|;4(%w@^10ufppI<1JtXq_l_uC0aNQBZdUH`IKRR8y2O zX?d6*EH@xaDFxP^S~`X#QD|xNlBDP53`4tkjblA6r4WQ+NRlKBq6jaq@wKouW`8gs znwg_9RHIg@UZr)k$%+PRJS%dZx#Kt}m95jKr6=jHc1Z>ag*y(>`_7ZJS6gfx9zv@W zZ5)K-ptCh0y9FRKrAT6BjZ-tYGCknAUPhq^}Dc9&U5`v6KAVUmv07WPJDmhueSh9aJhKw2pp_$G^19e>no3 z1h!XU+Xz$xSc)rbf7b{3z)Sy;-~Ee=q|0a6SUbZ_2cdNEAl&#KUU&T|e&y76nD1`j z=k9CJPYOKu{2b3deTCU&#e57+zs#nwt%U71u9OV=J&e+Xr4rg`qCuae7_P(AMw|SZ z33O&5&rCa@O%9)WwkOk?%vg)Va;-#nwaX+5Au-@Y~}J?#Mi&_A`kwLi=1CpO!*C_N@J8Z z@1z{~2*;L$Qo1%B(ioC7vEDz9$jNSEJxJRo$Qv>xtad?Jy12->S=xZ-ORDt})0Y?N zwfo%q#)H?+iT}1;1V!cT(i)^mDb|VI)ZkmL*V-i4Gra9HXd;l6GtjxFoO=_kU zT3WedWvEKO)nfVROMswQC?JJHSS(u8CdWZ(+fbYQuE?~ZpJgPm;vs>uwz7_dj)+ZQJ1F zEY#->@h3jZ{U5x<@ZpcL{k~u1KYenAkN)s$DxcTFIi z8Lqn>nret6fAuY=N<~_vSgzE)(j-=OXg0Wg= zDP2mn5u_6%vjIV=V2!_&eSTW!6mns6gq1RgH2@%=q#L90Js-yv%q_Rsc>O4MzV%jS zrdO|>6Tg`Gk7b$JVpK}C=JQNE%3NRKD{EmFcoL;kqQM|97mO_>gxw5T&a?MDNu^x2 za<+CSe+Y7&t8bGE9fWk&Q5j=wO{&3iRE!}_6t3stNV}oZBwe>J6uH-=bR{ZNJpZjH zDGk-wcGF(ces1^SIC!qN{{Do`MYK?@GAz!wx#PCY+oHZiS0*Rk5;qIPkrz(YRB7HPC*NJ{tPTG!I?Ag+kALC z{KzM{<>m%&e*F*^7GWu}Ly|LS&9Z{r)p8f?!xhk>~U7OZ*+>=hv#v{6_ocQnD?EX_fF?V=E zF;bTtOGdcT_oxst7})Z_b3I$*=jUdYTU$%l!C*zvp6B7X9+}c~dR@CXb8J4zH0?n~ zG>CCshg!+cji_FgBEHHKG8QT{)^#`te3UYzsSQ~WIfKrT4y~m&UTF^#Z@CM3=`4eO zA7xw|r7?~}lBk^etnDe6H@U0bm?8n7_`w$I}6Wn-+nFk*vDEVv(99qC~ z2Nqgz-6-hxB3$||XL>iVEN`TkAvZ!^Q&jmj9SIhwDH1DvJ_=y#7ybo%(*{Cl0Y?(+Gd|`5*A|*^9Vd zKq>SwLLrRECyZ+}WofTvAu!T91B6nN#0jagHGh^U!jj7kcisr4fT+{WDbyOz^K8SG zBSA@=+Azyr6vK=ZK+eD?Dlwih5A!1eoK-`lTa_?A03@$gez6o=URuRNaqkKf?95_~Np9`q9u_#xTX_T>S(0*bV z#8xxm8bg}e9x93x0?%5dcQb`7OAfwvFTwS{DPibp^5IN$s3D@=6_yKgJ8wb5gx zv&dil@}Dz(WtiXp$p(8SLMG<~Pad7&{P`7D`fxdhMq?Ajzy_EJ2OD-^nSVCy+F)lI z`36wRkOG6$Fo>)_zaunSIE0}`n#2eZ;yNDjAYt1b6Kvc%!ZVNm=y7%AdNaGp`=~Pf zL6RCa6g1t+2rtB=grqoF{98(~p1vntcbzxCM&^lQOP?JY86pULR-3CNNkR~KHh9?g zErQUV$JYZMJwC_ZeeP*)yKxgA`M>@xL+OAoJ$NLK3=#xENU>P3o;pgcpVqGD;YvxG zq}IvbUs#`;w{Iq#*DdZ?M>+)!BNsd+d% z2@_R#y06<4Y_&yU6!W+I2WlSU{C_GravZ-2JY*86Pim;^8Ow zlaD{l(~fbd@JKWJoPsc9WqFx}nJI>gh!HOC}naq#Dc%B>!2b#sZ5n3PGUxehbWhdtSqlE81yX)ARJ_FPZupt;iP>A z+T*r81;)k&zx$uQLYyitzA~MU{KXG>`sk}}lr+sq)67zl9S5bY<)D$)yvYcMvnM*8@8~xxP){Z#>dC0 zRI2&L%T26;0D+<3?b#^PUWfhSGOyVIM;7dfQYyl!8F==&J_r0qaENi2mIy}#H@1CcgJz)P0WvUzN9P5tZdoefe-hs#>`u!MV$~M9XgOC!PWjHyE zsg0dhXUdQ%+xH9-LoWs+4W4o6cT+B0X(EFX`ztX*W}KW_V#VvR|F)e3)e8La@gJ>H z=UrRews&`{q{=lk7pq|~_d8N@bqqZs-`aYme2>uF&iijth;0%?*`t(2+P zYqVP}TCFyoXFVvjaBvVr3sX2r54TWYW@_^_>o4*6qtD|vD!8u9dH+}Y z$=C+eCVi}lS9H$u^awl;qkBkK(rNZsm|Efu|K=_H;F~Qv&6CK9BGPpc#UkZ$k-lRG zV4ZH4Ol5e!PrSN9nr750RmR3g@LZQczt74_lVY)CWrfBLdW5kHg)Bx&htyPYqKmw4 zU(Ch_4)WHmnom9WB2f${C*jMFXf7Y0=K5`L`_F8JUGHc5)G{|5JjrX`dj}i$?qK%B zG5+@VKE-z)xk4l|w(f+VeYZnne2L|$KL6?i8;R4KxbfBzT66P!?eCBB{U>J_gav-} z6Yu21ACjDX=m{S9?U-#tg7MmbGs}5+oG}!O1w79qjg#Dz*ZHAHA*BsUTQXvrKtHla zjcW`uixIc(bou$8-o{P)$B?BmKRB|5?zt26dNHS8n*GshZWZDyt$s$`HSFF!%)=|g zv?Ikx$w!+SQ8XYLSS@Mb+hLQ*PYRV~dBdnF6pJ+Kb-JA{&D9p3=h`yBvAmpUWfqzB zNM*>Sd5uKy;&jH({@U{lIu4r-4YANm*BPPus-%@Q+ib1UoRJAagAy7?You$#%(PJ$ z0f*jn8^Pvr=C7P%XlxYE^DQ4A%jJpV#FEvtVh|1Jv^x|_1$J)R!nW(SkY@ z_i*gwOSHQ^w6@Gn*Y!|3V=(AZtyOVd$w~+IR4#GwX5jkwB3B|JUZmBxSL&4oI5Y-( z-cX=5b|;sgObCK8w%_{zx;f3)|L?!yGk`QZ5(r z1e2WLr8J)J5d=QH!GKP?ZDVX4iR<|YDd{iHpa&iLgp8LIfABG%hmMx`%r_Ugbh6FO zTdFvYA6tFDaco@Ic|@MpE`kYNX?05F}|zNmw_xdZWnZ-J6+v;y9hJ`G>!Lh70owf5>OD ztJypb&pz29Ien64XA>*YM#jct&R%SC_QW!Snv2}9A0aeJPB3%Oq^Y?IF1EufE2hz; z8FXWVl!oPYLSJf9rAV56{2g1suK*!XqL&10+FE1N?k&L4AFYMo>#6ST`>OTT>IR-Y zo3W{^F~&t3L)`14mBw{lf?T=dM$&3vb0|30|Z{t7w;kW4aI;5Fd$M8iS`?oHF(K=5|lr|_rDO}gHu|!&6! zvk{KYKmgn}4*T!9mx;UHK`}I(e(d{v?ytVhu`@kPU^sXX{{7#)minF#G5x*2=Z`;n zk{j>6myxkDr;Z%wdtZNn?>xRhY1bxx=TC3to|{hnztp{Fbe-k3wtKyG6)i1EOTD<; za__xjV|ob$0|5d_2qXjoA#IaDNNAf-(n&%{LJPgRP>caL+EQF}V#wpw)Q&eC(p6PV zOg(LkEX#z$xfB!@;Mz8)`uYZ<0%b)Z(Rl_p-G{9Bu^bp2Ns~&$U5}_dAw{|4n-a%A zh37wzy+@WKddxTjAh>=tprQ)LmV|_?DBkrfx=S*W_u!R@^~8vE$0@&Z0b0!&kp*K} zIF5K2tBOocILw&JN-9T_hP8d~|(RB?A3CnVEESvV0 zHYD#BiKcbFbE%IbyWzLL>1JNV4lce^<%+9)?07cAqqj}s`wx8;Wl#l;>o@cKGb{Oc zbt{F%(5b@c5l~qQpFh8r(ep~t0;9P2+v91kuH(JmeZto5O&q8LF75 z+PV6?K`dD^gvwz#oIZVqgFEUtc)X9UltWztw9*PH3rfj!b>O-pp2RY3{JKcE7RG(Y zJ2=Gf%Cub?<8X1g%$(7q$aH42b9;iu7MJ$s3=jY4bLLO_oNI5M&a7`NqpKsq#=SA- zjkBHqeKo!Vnx+!)t2mYg2snd-EKXQYf@&E;V=s*0;`E4w!;Ba?5>40X>FmIEgcMnl zWfHyZv~~88njosz5ed)2Y$AV!}f2GL)7W-1_)3_C1^6fv0Pj zH57U}vRO25E_*K;$+W9xkvMjoRd@d4o zrGvv@MET_TU94Pwl$y3QQ5%dbkVCNj)mm~s^$`oqrf7UAWmX@beRPoh`&wx3bBUV{ z)0gB?=qqRcUKJym91!HGl8A8e2Xrh;1os;xq*# zQ;ZxQVb;h9=~SHDh>9u)Ir`Bde)q-+wjXO}eC4cr{(jGS>DLc`@$|-x{I59uRo4bZ zQ$<*iBovY^9+t=MkLT`pJ$WUzB&587tPt21wjnHSxGsvSl8nbm_jGg7>X&Oj1_sEaJqCR~(* zZ5fQ&@>M+EkWAIVB0o1;XEwcrmDJ*?w%eb$DtrU&%5Ouk0@@VXu1fA zvK%DGn|4|@y=j%NjZcF%glV^2%uVb6LPD2_`o6-#OXq;y!J5aOW$p5v9IUqqhT&U_ z;l}&N0AXg8Dm?S}MO=65MPR4c`QZls@rSh>Iq5QV9CZ8ObO+=mAl9j1&!3Ec^muYq zi<(0xS+V>CCr>2lRG>$K86#lvWIz5$5r3_3p)u*l&7_c}5PHCmuBoB~wGmD@7t*GS z0YpM7x6B_(zAmwKZ#VlJ<0Nbovqd5ijWMQ3V#2Uu6jkB%Pg>Y~a2MTei=NH}mj1*Ia1CZp}O zz$75x58w~^i6#0xDz{A9v~eFI=Rqop zjO)3z9M8Ohr`3@q8OQaav%UW>Hi;@aE}B9*ZL;gLy)3zG62m7d*axcd`~9G(7||$Z zCe84ngJ?d}MoU`9hk3Xo_*^?9I^Klfg*G>5VDiN-UdM z!sL=LkphctwY}`BwkR*qQB8%onM1%I=hJCRujBAP@(gi&QI(KnVP zugl;HxiOxWq`%CuEK`_TTrW~w5k6eJ&{#?H`f{>FtS>?Nhzbfv525pe{bXeav2BM; zGL9t4q|zyBY8$AjZzP>g5eNjZOc4<$DKd#zjASy?|KSE)TAHR~rP89D3yAh;z~@rk z47H!1Bzxg}Dz2JI&DQPw?e{A=alD6a3tA0`ltEC3+S5>UekJjlm%bcnNjK8~Et;P3+m-%;`>xf?~M)a+rI? z5V8|}+&Qy~X)}kBNt+z6?cn60F5*TAw{(~Q%sJ4~Z8EAv=8Czw6y`=qyV=z5Xr}SB z!E*9i@tT`%t5z(`?;Mj{(F`>o_s@+g%-#1>}aNy z!S8eN`Gm|Ml}ZaquWbvPp`zf}HXWTE*rtQ#(*^Fwc7#V(gS72>Bt5Z~6$T7QTYvkg+QBq!SxYL6cuQ&Lv& z{(CR~=Ly-de|pU~A6odQ&l|?&D-ADSKD+dVm%lyz;i6ps^_M-pb;rNe!gstyD3XgE zkVM*9CX*%>i=+Ge_;d}w--m0v{Xu^?u7qVdq%sbQ%m4vfk|bnVq9X}+EvrD!(RupM zHB=ONLn+zwyV_u6glGo}29KpDAt! z7f^H!U2)m;=eKz3;axNs@Zb{{aOJ4uT=e~Bwl%?>b7XG6_d2Fsb15WZZ2Rj=y#4YP z_Ej0oym%bnee8TjbbY{m-;Z;w8oqknbVgsknB0iW(G5FT{>EOm?u#;Z>13Yy-Y|B& zv6A=JfvV&q4;_zR*KoT!_;gJJI}Y{{GhJ#;c<9NCx&HD|Oq%{TVwrp-+2rdNC`9H| zKvxh_K2TJO$9|ayez1>we*Qkeyb>0SFJn}WMPFAPA2*m(_ra)ah51uTa14`BKq2D< z*s!UU_jYvC*wjXzZzFE3YfN~=gq52<{=><-)Ac|6+P%M>_3E~k(Qj;PS#jHvA=^K` zZ^26m)Bf@GzuVsZ?{VULT^k7(83#p{Ff0qp11^hhi;bqK=spcam9cG`q{nn}Y#YaN zkx;zSM8=jRvNTw~yNldhmE5q`lXt-Fm&Hk*Sg@a>h~q_vc$=W#1Z~@1Nh7#gnooo% zVR(6)l7#ChIIg%gT-PDDFihvEW={F> zqDYwOG{_QxU=U4~L`sC^2-8geC$Gp97Ub~JTRUjlb%=#GPUTnE^q}Xe{O#p-id^{J zkIv)!4_phmSsZg;U`tLV0ebE?}-f|U@!W^o0?c>=e zzhL98E;6#ih11}%cjiNQGHl&I+wcQ3m)9cR_*dfNM3#*NqM!eVSh<$Lpv z;EOd-p08rcK_tuI>ECSOLC2(W$y_8O0old4v7`7pYnVBzjPu7A676VVV{M97H;m*9 zk{eEPw7Cb@wwX9QLc0a8Z|ml0-D!e8hYK#AM@@4l$5*an=Hz;euBoHT$4~fp_qsoA zKhn^7{;jt@JnoMh>TmsUOZ|&CTsY#^_kS?wXUl%K2%tL~mP` z7xbiRNU|(wCNNNkJGO;uny8xJ3x;w$cB@RT4{DoII8Bfj7Ve^fiIfL6aRA%lpU^e} za3&1|bvmx#=Jum;9PihQPOG5*xwebat<{W9>J|9y6S#jaymu>m#Sx%W0lUN{G#u0 z{;W~-)STv($5ya%#VMp*jrRIi3Dy{9`X=exAa&h z%pEm)bnNKXm%lxJ{x@E#GkNLB)z!Zrvab5^2QD9Z|GaTU z51guVpa0>z+f)C)EqvE@Fbqr7+kmFXIEsi3aV2r(;|OW6BrD!SQ&`m;WK7pYRb^B~ z8z`G>2XeE(l|@-IApAe49cg<+6Bt31Cc=(T7ZN?4i;?J+BsOel19V##E=w<2% zm*IngB=d5ytuCfUWb|x5YgRYXQw6gwswX_C07X`*i_4_4D;Ql6JWFR+6f{-Ekt8CD zIIM<8R0c;>78E*Eb^EC6F{tS7W!aVUm@|6*~qRZ1~R$?*C$~_3MW>ZnXaAPkcvA_Dsvh zv}GY-m1NP=_fB_Lat7*f$up(cmW_mi>`JJrf~NLQRNVo*=YW&ML#p%#&~lCt&2nt9 z$vict6}3pvH%>&&OkJX*mx5DU;xb)fkz59Qx}dSJg9&~v_^dMG!0pja4a#s zjG74)2{c`BwG30-Caw!+#-OXSi<+8R;;9s+#l^yLWs6)MRa3o3yiHC~kk+I7*!571 z>=|F-^8*)x+sCJm|AqHo+Q#8Vxax*%nrdK>3YXn|1&eOD48=-w;KR@P zV&x9@9P8smkHe%%G9yCGR4+e4Ag7#5Z=cJEv4iPrZeqi#-MsmFHNN5?U;A2w%?G<_ z=z(p!9JcN0M9UdUzMkN~!87bWn4qZ&%I1}@=*m0DG#uc~4-YW4GMnqK9mn7y5t12; zb!(2%9@UvJri7#tptG|R+i}r#jj*gxp6}A+IAp9CO4_2K*CJzEwC;?PJG_!HBT8^B zgEP&Ydea3QpFM${+Yhj5*GaZ+-p56kF07n>;rZ|E-S}4{9ZUaw{+0LM(qm`e zd*@3B*4#F)?1?X*H|p^XOP1cWo_isYa=V75O*C1Nz+8? zt|{z)k~id$C0XdaT`_=CaD_=k`sWk=TwA;3O$##?xRN^%FXEmP!rz~~0C-8qGLGru znnF7yE0XA^+v1Tc%QCiU6U^4h&J993gJasl2jIHm=5Zy=bV^JzH5FtTRS{+q!!U_P zqtrIEVwxsCO(iQUD2&>sDa3Pf|1eK8ZRG}5EI-b{>NMAUa|U0(Zwa|o@6mLkoBUxTC>}M4cr4DbLk*m&?ja-T zkfT#D$lzp4indkjxNyk=ZoYaVmoM-$dQv4Z!)4pSRz7)kE0(5_J#q-eVIMvX^ z9HHG01^i?M{q!Vqa7+so7b!PHZh0}|hL=*D=NE4^T>7F(63H|}io=Y#7f1eX#A!TQ{CR_^sFPn(^bD zu>U((Jh^4>|H#7c2PsS5qU#TLwQO?7>5J`h!7K^=$O?faLYR z`9u3HpZ$TzvS(=&{?Bt#l0D_1B*~bjfn}N~vLbRXT|7pXgK0|yBm<S?NJ z$LGt($fO2#pRB5)6tf*{+eFv=BoYbg8rx{;=w;6MG89E&-PR-c{4%<(3O}z$6}KG` z4(m7$wrw$_awwUOGyLsGe`fQxc3MpsIuXiCU_zO}nme9i!>I@lz4jo3=8mIx-(KE- z;18_+xPewjqB`Ny=3VlaWWo2ovw(S5FF=+hj%?h`o6qlJ(}5^?dGMPbstmp)$P2&v zh`e};FWtD5oZKKgw$-q6XB~rwMY#F)nS^uvjG8f)?T1>q{r(+HC^$w|=nC$*|9jMY z_B($4=n51~VcO!!-1o$lY~E1Ii8deESvsL?A4Pd0Yt!-Ax~fk@Q#2%5!SDAI3Mfdn zDJliaArSB(xk8aE%M$TShIl$j*r##xjY~N?V;mp6zm}(;dY?t}_Hfaa=NA-=n(*e~ z9sjuP^zqv3zI^M$mCvkim=|2%@bOLa%J;l`@9a0rhveQp?}wju|KDBsmh16U`*rVv zJ}5~ZzD-g^iQ(1%me*#u(| z@A+-bcfGc)`OjZpP;uj%cg=VqI~4rQ6;E$E{(t9j>o^0~mFS1N9;a6F>TAgpHHi{L z!S&4BCdovCy!>2j$M!Jx=P+*1!Kt|C*81L5)N%VKw`U{l`ge`f?~d@IOGJesAbaeJn-_k{XIKbB~8N-!x zD;Phjl$?rTgocmfI(aX@`|ENthUMK5wwLxGqbZ=MI<8@|^;jQQT<#~>kY?>M7}Eg< z*S4|nD>rlgcNd`AQFg!b2Cw{aBYSIHrd=?a?>$&X<|eJu z{e1bBrbq9+cFb*C9>4JUQ>~p3eDja{JN`c%U^$+tM3xot`t)MCWl8oP&6Gy)rd#q-l+|iZK2BlO{pWF)4%r~x2|(;evb4{8^rZCrELibw4$k4mgS-B zB`n)(bt00{EZf1aD~uRdj;zY0lW7!9@jiD4*D}#m4Mo$4M*BE_LJ?QY9>ml!MHE&H zCab8Nn#MRSn|{x!6Aifdk!8=_WeXjVKPWuG>5NTVdxB+iQ+($NiElg%u`ZZAZw}Yo zaSfqJnByBh=ar}5W8JO{gNMR>59M?9w-h+NfnzV`@x7nkO8$)L(A~-UU%$=9j}Efq zL>yOlx#j}+#>EyLM{SO+9#7t=NnAW#;nbd^y!Xaoj@Fq>TTo0+x)-BYW6AU|D8xj)I?kcNRMj#TZd|oNK3*kX<^2o{lKlksJ=xrkUclp~XA#MJn*C;P>gs ziiE6+gG6#Aw4k40NGB0b5|1WGCX%FsKEgR+3JN3m{C>JR`$(rU*sgI9%B50MUNcY@!EGx!+31+qHjLd0gpZS z-if~~+Ew?R@83A{_KlBS_={DCj{o|1?>43W-!FWRCf={XktDpuE~D#yki=Bh^%k{b z+c;j&QBfqaLIG?uEezi-*tR7yEjb4W-M<4I(cbj3xrOuRECp!bMgbSamA#W+03$^I zQ^1W)%OM!>VOeP$TZ{-C)%9)?k*{N|@QwHY&<(uKY?VQ9~wEpXO+TMadAE zNufNl3W|vJ1~|EC4|{i$xm0FeA<2Z zVR=i=#zozAea=;X*uUxj{KWSJVP}tLSF{gtQDt@D;VCP!r@)kiSW5y`wur`3ShfI( zo$buuLa$Q%^{W`mM*AgVbJ>UK^2lqEned-9Z1QRBY;Mg&TEo+lVs)Z~G zDX*rfq|+%(!@@KyY|F-{Da3*^Iq&WTe0A;;Xlvo^??26|_l{8243}P!&o5T~67|Fi z?zwIa$3{%%f^XbJ`G`WA_iy9bM^>}?!!smpXwjf41!XFXA5_SquPvo?^ho-en%MZ- z2fX!0HEF-X)G0QL7W!DerIp$$m*OeYXiXhr*Ue0WO}1fvaktpRTDY6*(|$y5wmAcqW%Tw#TzU24L6Kpj|GedszdYho)!S!Y_^ri% z+tfHh-PE}HE7OagTK)KWU+-Mn7MN3h!7$Vysrzp~zUR5+S1){c-Kl?FvT#lfE>aD= z@xS9>V<9UVvZsxgmHx#okuh!hdXs|3q$&e(6$8n;=d5~H5jm2wx7LxpY$NCFhHzbh z{*>i@v86PC7IiEGMOD%LevjrY-WdVE56LH^8a5cBHJeGLLH6Pd9T8io1$^Fy61y&G zx_rK~4%>N+`E!D#-AWWB=1xfQvpc3yXN=*hdsfp>*Mx*CRH`WhU%-!|DkRfsGRZi3 zL+4R3O=ImdukrDl+d1B763m0EE`eJw>cee5!s*(4e*X8nDVi~d=*c6zdf&6GT3Juj zg0DY%5%b4u{PepYQ*LWKeE%gZzG4P_T~T(d{G2tb4zj;qX5!M3+&Zt7?v@l!ylt?v z&Sl!TEEZhXs7?AUe+zid$4)JIQi4+;{^U9kDHePsC*QZ{rnwG&fw_`~Wm zTsH^;p*GB9JHcQXMa9LKwn4_Q>FtgZ%=Y6C2Cz**vN0Wttn4tkdAS@rdWt=}4>M`P z2#N|L#NsKM`eKB#1E{(vNo~_6ZY1&PI)1-~iVTV*7-WWprfWp|67=@O$q8q1$L&`z zYu;que|H^!`s;@*opF#UGba}Khm2pj>62%-G}g9%{i}C9JbK8;(62AOZRU@hv>!QK z0HG38IWo3nLEYQ1ZtB1MxV0T2Q;-$WpO;*4aFM+!tt2Z0yZ)>p#iO6tF1~)2k_0j` zsw!i795pNq+a(xMQB;MTPykXETMnKft0;$y#}+bvXo?|==E9&k3{SQ* zt|-Nk;}V8xd0C($K~0urbWKAI>Kxm#k2R04<&*6(3>^r;luD@Z!|uZ>(<*x@p1ugb z6=n6~&+zUmyNCr#2#y}gteiS-x&92X%;ntmU4!{o%|^@dvG=3xtY5y1U5C5b*XVHb z_1Qe~_BUAZ@N<0Qk8uLPxID-z9n0`B3#iDh`^pWux{;P?!5O(E?Y91y(d~x91Sbp1Cmgl27P{PNh6)i&=*aRHcVt$A()j# zZe9VF<xJ5x~?Nj zKGNw7=~Mq5st3Utf z`QNo|esfUMwj)$rdOr9=KmgFN9B0Z?*N<58lXt2&{7WakZG&xE^lS5xBwWk#xKb*a zOd8v^M1rv+23`HP1Fnl}XF%}}%mMmqdj}zAbY$^kf63$8XFEOaIsHy|;LjJEp#OKc zjyvGUGBYNoVGs=Xgi_PAFbsz*rC&xYq3bF}+QiI=04d=&wXj_mpXKH7NMcjZ99zk} zP&b!dkc81oA)3vu=U;*7W+Wqk9*p366h>E;!7`8$V7q`{S@oksWy#F9; z{&PKh_cU{))uJ^4gDYTkc?=R;Q9}h-Y7@N{IK41;@_Dqiw_@*p89$x)1BEP@EFPa* zPo`-i$ifMQboHhQh5RhM=NHthdVy%;Nq+w01-!E23@1*vi=m_}kugjxLqZSe1VTZQ z$u#MdMP9xjJJwd!l8pDF%QC)zkHVr{BuQr9p(?6sTbMF&1QW&#MwTUF(G;TV?cmxj zsE{!&3`=Z^fZtChV_;-5n5Ka*5X9&6(ca#T+||c|sl%8tc{m?_x|>}aw^CKJf(sVc zP&jGE4}SmZ0p5A3i|fDE&8TtZjGQ)w$nXkUx36dKvEI4Bzp(H<3!iO!(q30AJXsRV zSldeulRZ|_0OeVr*E}i-V4I$C*%=VCIfxTo@n`#UBA*5Xmvcmn=y*4(PfjgmI2Uv?Iplw=d<^n-mIg&r(CKpJy@R;-^CLX*nMH>SMP-9XcOB!YKb=Ch;D*Hsp7>EI zdgT}nuRF^39;{`Vq(Q3ZuvRZuk*S@Ds{7^D(ObiaG*V$s>;AWzviPcJPO@2N0chzx3docZ1}e@)jUz9wge^6#Z(;fvIjk;?wS5{EqkW zgf-H3gcrbZL_Um9*O6rvMfE{iOmYpwA}c$9q9sYCqu5!x2)tDk@eT0GFHMy&9GllS zo3wXqVD3DPh2zUuvS2uwsL7h`1{q7n_P#bn2G_%a*tSDDZS&QeBNPsavvb`zzWLOJ zl+2q>`>y@0_}Mdjw5kC!Tj$#k&f@mRZU)-f{!oyMZoPn|H(iRH>SWVvuk-rfwsPdO z!}uBbTskeEReRd0s_&yXByq6H;r?G4On+w$rMV!<t8%ZHT_>RI8D5bMh@(lj-+ z5DW(R?l&*uSoI`6_;3gIiBnV#4U(g~xH&Sl)lvTX{(G$6*-cJJ+Vy{+)p4;+8(CJ6 zWT9G=6%|$0y@(G1V(wp{k|gSBNmhsy|G?ik{&;y^ez3mlhJJmY1< zi&O;5ve0!MBO_c%{TEn%ND#o=`vl=!u^c4T#ivX7ba6t-nl{kQlDq>TnB!;Hiajit zSIU&D?!irU@!n5i$c^Qtbhb94s4{tx2=PRk(=|=RqrHRz8num`96VM}O-m0B5Kai>u6#M zFDu~jy4uwYXVBObeeV~GSc%Q8u{M={cAEZauab!1tlD-Aba zSU`K+V#}^x@6B- zZ`NU&Dayt!q;N!t&2PWQ+b?cm&!G&83?-vsLM1exh_frZg7OPyQaQei=7alL{?Ny4 z-PJ-(kIRq}cjB12cgpg1qU%+V17*+D)(*hNNz-+Xr(+0j-?2W9;@U~|)F zZ$J5GP0D^|$@Slj|F;WY@yZ+5wvi-H?dZV|K=j8YK=USghGF7ZqV7$nQ^ev)9LvH? z8v|(w5-w>6RG&h~1>>B)z3bKZwtcqbVPJ&d)tTN2?|Ls@S(ZW7uq|_-{#QL#t_vud zhU~~5!qf3klu6>T6q4fU_$38o2U&83t#H8JDBd0Mj7!XLkyRTr4Q9r{FeNP00l9x; zxt{k|Jfam{rt#1 z^D3HSE*&NW@?q9=PT!p;CT)w<$6w!_zI=gyt`BIhw^N2a$wyT9b9hxn!Jg-h%EjZx6QkQZMWUes#P1g=7CBc zSqAs7NRu;oDv4MR2Y2tpNcIxWEkeYaXj@AJeF_=V zrn;$z*7iPf!$FD*!xR_h5KE-lu>CN#P3_E>G>VGiLNbO)I%5b%m+WPGnhuVg#_w}c z6&YETaTJhU3B@14bYwb@ALf#g8a2KgKG{-3M9uKjUDKJrbPO;5shKaf9OB}V!DW`2 zdfb)lyVt$@^e>iPci;2>W#MZQ<*wt3C^_%TQsjPWp$Jx$B}u&e0aaEoWP70f=$aO0 zCXMb7;tK>wXEMTsqQe^>wGj?LNdz3z>)Id~OSakH-E{xSYUsLxx8%@Y{)oq~B+CPu zd9fkw0gR}FB5o1yCpUGg*+iUPqboe$sLN7IRJQdzKc2FxANgeG0Wy^nvNq2tG3r=ooN>p$_@b33SN zg$ox!x(5!Pf}$9#I0(T|3u9}Zqq#fhJA@z`B5%3m`vMD*c`GUKdpO@vIDrXe&O zNVt-OX$gJ4ZQBFTHc?i~L>)+rO^qUpzbMNEO#@X1*E%<;7hIfyI{%+EKHl3`Q53Jc z;taG+g-lq$*DOy;?emE=H^Z=SZ4=kEQDt$9WDMIwl1idh??+tXVmT7FBLr|_!Y+B6 zt^aZD;5Y^jHo8woL#8EVax?+46c{O}s~Z7^%h0jI+4I3_9=Yiu9{u?avd0hRm%km$ z;YL_f4c$rTi^HjA`1$KDcRp=1Zqj&0j>{Ef@`f(@Iyyu~eISG{OUJfNP9JG!|NeGD zu7w$GrLnaGEfm4ApsoWBpMkb6$j*^CUYnsNQ%KIZ3DEEw6$KKinxdh{hn78t0v{B1 zuVK%IkLXJ~oI2IS=Iux5?2Hr6QqVL79MNGC^O*k58>o_S?nS~r@m5437cpPe)`OQHl8vlC)!po`mzc>+tWv5bBw$!$Wo!M3%+y1U{pIrM|;PBfJszzlE+?k27Cdc zkB{fK^)N(=Jiv8w9O)c%r`U|~ScZ6?GN3041_L;bLo$^S^mT72hIdtSZcMf*1`qvd zkdh>MrI9FZ9WReXc5O1LB)hA-2>{=@c?#FvekFmN2nRn~%e&8f%)!$l@_X2Lc=Cw? z!c!*m+M7-EoQ?s|;7P55n##AoG@AKShtSZ}gD*>`rJ;}RU9Al2amdQi2>BcmhD|(U zlS()Yj<}Tg3=SMR&bY!-Bu#Y9>e@k*1;R8(fejlvDVt%DTbYl!{8NS(92Ek;2>h=NF%R5HW5FZOfdWIeN{R5H49D3Sxc@g$b4p-C3SRy!>xPO;(G8ETCX zPVP{QzBsO9v%fjPvbhx$g>;@+)x?43KBkrg7&>Yw@!n1{rh~2raFNK)$wLqLN%ThZ zdOEuv`t?t)->w3DT2Bi!egJ$heE85iUE6*TNh)(Bp`DTXOA^P!0m%}sDIx|{MHa&# zGmWOHB$Fvp84ES-aK+LBPIkK-uaDt36>x1remHono5HZejDmiJrh85c)b;F%l1DLd zz0rY-ZCN7iP18gfW{Y$+Syhp2QOn!5K#1C2KBUj@A83mriFD`wL7eNJ{rI*8hUKDa z!ryB}$WfzR*fqSPje9lDdc!u_>qh#lY8F$tBWba?k z`h75E8W`QZ;7UCHqe2otcL@wG!A+$o)L>|_j~QbF)Hn1ZYXSV>48iO)yN`8K-`&XM zkzs7ZqN&RuZ94c>h^B1DPywQVrAOu|-N-u&ICTz7Rj z{`OV^QXzc_6Sdq&Ck2LHX)+E3{0g3O z{p*^XoB2ufa2mDa&tp8xApSTx;-4LYGmk$p$sXBP~nf#+gQVv zL$y>zHIn{v%7+!uaHgB;+IB|e`B^ft2)|!r&Hh##)8Of^48}~P$XG7Pq)9pv#|oO{ zU%Jb{f6`YKq*<4 zM2+pZ1G+Y;pJ}VAxQ>t+%U&rWc|*2-rKe@t@gP6apsqz)vq`_}mDc+Yh4$1C&miL1}0(ldsRC zealn4yLcrpz6TpN*06X?4V!CVV&!n|SvH)wWzyah<6u<}TlaL4m763#FGMD7fCl(A zn!8h!x2Z^~Mj~U=n=r`i$(R_+9 z2)Q0m%}dX4Jh_TbQ#fAThay3?PeI0|vnNG7o+c+ZNFnuLe>vrU%P7vagwA zoep+nBn8DjT-%{5mcq3z>pEQ16TSUra<@ zQ#?$BNgaY&LDC5yCtEV)X%c~e=B1v=q)io9mB~0ZYY(|Jc0tJRJ#@V`CNcwn9BB6IMJ%BUe(1a+HL>#Hd!2;lSiFeI6lo-~=xG`XP|MIoJ@jM#YD0fnmeG(+ z@8ird_Sg%o!OSTR6Hhzz#nP1eEJhca zSjjZ+@9E)4OOhO*M~3xv20PQaEVy*>|I^-^N7;FuWxl`t&EJ_%otjHkDwRr-C0W*B z+47{siA@IDVQ2^q4K#gk)2v0)+|{>l(?AclGusfzqGWLw5ra2zJ1>Bd7t-rxaY`z znw51HmgiVstq?{s*{ybbloF2xvHX?ye(3&1V949-x z9VgXg^~+!2dv48QXVdH+Nt1P8Zlld>b4_xtz?*9@kaI|R7M2N}Fy`u71X2(vfkx2? zVj3MutTiRiz%&J(D~P4Qw;hg-J8T3sPOfMM3xcN76f?;s;`*>whw4R`8iq~_LZvZf zhcBFrc=k(hwPE1d;Fuz5Rg_Mah(vEC)X+q|HgKrua^%(_o_%Q{37QZIA1+AJ;jj1j zCOuo3>w+x-+B7hF?@h5()MJfj8GP^I5e{z2aDH~3$4{;x{S@O z6Taf|g)7VpkEU0Iz5;uT63Z0$p2LSUstoUvtI_+sdS2Zd4qPVjcb#HJOgXZke~gBTUc&tKJ$e&4o)XznQ5Ad^?1*>=ejse#R<4= z$L?wG>9s3~+ET|MLO>WQDw}N%>>ee1r9%)jL7TmvUlPS3?N+O&0s2bPUpLaU15i$q z;cEb4@81}Pk(kPAi7*XT>Wbl#&(YCPz1505(_d;vNbl|pQ6u!D6+U#=}_&~=}$Whq-z!|-N&zSr5Z4iGx3d(@_LntfgIa%2A!)H zIg3Ma+iv#n-9a{=C1`ihGKrC$m>6ZKzn^lY#|KjZM@bLF*t$#HRqbaQv zw(C(G9;4H!)2vo#wL=`&MrzGq$%33oCyZ~T^IfOJl$02*xS;|yP3y)tjWDj$tUZ$} z%ej$~A_RjECo% zxR$^)1u}v-RK%vqN+aTyL7$aYh}MFQYDg3r+){9{gkZVaW&fbdU^aQkBdN%z9OgH> z2qlqHGMR26+9pvbS+B!#4YEGuQwa)JYp_&-=_wzfB6QHf7hnjDWAtR^I-xEt4X%}V zl14o`GggW%Lpe;X2+I+E3LIguu-v2@YaHA7O0Q#l?e>uY)Pv-@-#?M(=yUjNPNVwLq_bHvnKboAgBM>q z$+g)9T-zp_P7}pS29f%AOJVUpf8rCLkpDx;!r!*$mzEL+Xky|QEMZ)D{>9@rjDS{F zR{nHoXz25fZGA*a`S*3Vi(#0g3kBSCnpSm_pjjht!moa49wA`sPzsDhlB|?Q^m=$9 z#Es3W>$ZZjw*#E8KfS1+-jE5AC^)aqtdpD0Qt0ytE_HDVS!~-$0;qdEyH*-)CM=L7 zVRgD)1=?B9u>%$bxyqkCRp)rEkD**ZZEcN5kB1!DHN;)h z<6Jsh<mf9Ualw=wQSOKW#IZbtssy87Z#R zBZOlSMajUdSac!Q%$Fk&U4#i4%fQP!G&_pPbc&}hM^xIHw43z!^(M4s@~-TdkjWQl zRVy?qYZTMakcr=rWhAqeuGC5Yu0;ZRnY1pUh6A^au(({OJ=dhzyU9DDMp#LYFU41{ zktUZ=BS>(!e@m8ocb3T8f>U!fp14qTfp~Cj*ox0A;d3eEf0mAE~agh?H|BPX9-(Xn$>#ZXqGpyj70r--CRoD zpvCl8mfkI+7ws9|7<`$+zOm0JgdhrIvRRk0@dC!_8n)x&dQS4S+Z$M!!niRlj+IWF zo24d*K^Y1i3QV1}B#jz4BL?r{gcvf$iCk3@ofd++>+4n5=I0*)9@(~a{9g$n z{Kq`*zORfm!Vy&5Ozb_?SN`q^?)vVY{GSpJ@IjL3>$4~;z-;O(iy#B&2@pB zWt(^@n`X0%W!w0^O&kOmwhcxyh>PO*D6ix`+#JwhUiRKm^} zU<*OY62wXqYH)4A@574IJ?(q!-#N@yFUFM}>dK)sxsAJT-%ZA~SYNAf`AUs++9y}cAuNkpy~DMO*QnR( z*+F2^$Z-#_??XCM7r`|5nX>+0%Q#Bhnf(-o;}Uk8 zoLmX1h62|V#9H)TC#=eV>`BNxW>7ks)>6E`JWhi#7D zI>0l}uCiJW6Q10JdI&^{YAZsdU3}YM&=Pb5#Y#J-=$TZi9SqaNcMNidq7}lGw!{~j zxEs+@CVtvr$TwN@O-6Epy7s813)E|MmNzQ2q7chA@Rh(bKpTQ;)B}WZ-3dnDSdvyU z8CaP;^{h6Mn_cUq4N@9vU5Nv{eQ!U9w-qq8=Jy}F%*)H|8-O<)n+I>-!GZA%t(7He ztq6C^4sPGSi!DPr8m$(an@wEbBUkE6OsQ5jsZ^?TT5W98BAZGRM3SzQzg3Rb{`Dt5 zaVGqqGL-s;fdA^%r-A#Yrlua!O1?)ac~D0R%e0VghN@H`k`Ra(d1EfF0LykzGA52g zEHtKV;dwr)-A)oxZ1V=KW*CXvTe}?+g~_x{Dg`P+2u&uHq!~uBA~s=mwaLM4S$^qX z+|6wVr_kEw;z_D&4I&fzi$2HBHQ2V@<>-+TpLt@1;iAiC zE5fyspDhpqOBm=F97j+KBzaG<*%4eRM;w~WFxQf7b`?28kg)_Nnv@9xd7I0d5+ha= zeUm^5`mKP?>JlekGg&zCEULVYmv-s4lJ^J0NN(`>diI5xP?lO-`XP#W;ru!;T&{8504D_Y@0#E{@0h^qY;x-48SLUP_r3isOpKPO z)oLuvuYw^c_V-~r9;@pW)>bN1E1PHq=}anN;KKO#q@mvX!9RZT!v8NPwQpoyXNIR*&P9u$UwYbLyJz;%6&>V+-#I5A-&42a_pDI;v#!L}{pZu~V?CMak&Lo6eO z<5)yd7p+We$HMm0*=5e3yUg<3Iu`KRr#BfYT4X&7--L}wC$yzuP!2VNDb3!JMXeU&7@)$KGu4nz zsEIU*$(3VpX*FV7pGh(6VCtB5C=*tumsTDt*j6&=^IBY7IYpxrG0^7{DNQHVM6&0u z(PLypZ5v?E2is~O2UeE01m>>JDSa!TTRz-=3|gIHJ5!CX8az*(|ASmRhsJ#gnJ0*Xm@m89dLU9Yl1( z_|rnGU;dqsKXv@?#6s|!QM0r2@1LHY{%9OU|4AwJlZNhvlXX4W~nf0W5lhw=VC z?7j@^>vbI4WbdKf9J=c^u3nzwnZJCRi*qe1n<3LfKAli8;2Cs#nj_l;4~c6!tOw9) zM+{?7iy&>oS|jP-i50E^Mc*Rr!fZJi$Q9By-7uMS=NyADHjqk_wlsCmq#h(74kZL= zGS*jG7sXd-P0`zT)*6)1m&+`Df(>6A;Y-lS1)kj-Zq8XBZhZE^PeHOl2OLTfzNC5Rp)jpfcoSp`;!{xf-+43_R26GxfqZ`{i7D-LF+{SDt2JzNVr)Pt zg=d0iD9)~QxvU1+Ix$9n&I3c>T8RPc+UhEm5xahHV2W{>fXmacCmX zGpASilb2RlX~s8N%?Izig?HaSjZt3U)R|eD{xEy*Jj{WE(FY0IS}wCo zYg{;gh4qzHY{$m)Jc39*rsDA3zx!uj{x2_`zP9-Fz?{YFsOIOFJ`H@PR4V;Ear|>q z$}Gabv}`njI1CcaO^=c^j3n(O>WS2}N`j+D#&WDIH&|PhXz8P6jM)>WUC-(=4Z%iR zva;D_&$fPU9Z6wyYb-6-sXua(%jZL0o2_x7<*;LFm_jy%Wf^2W3sXS7*~KsguARm- z4K|xyS}LX*8mz`?a?St;C$^HYG~FP?wk(88Pd}8RTCP$pSJ`)P2XB7+J$&hNPjl*v zkJFVQbp^I-Fysh)r7$g%aw{U2N~XHYt1ZUIvJ^bcQlQAX2D0Zqoie}|g4Kqk+SN#5 z;%T`37Mtx;8UC-|&;+J|*;^9oM!lC>G=Wk{pRbdj(-6=KB%2}hr)>VoeG}{)Omlv| z%7>p=V6CfeIOFY_8smHJnxG&XJo&k&QMo~GyZ6oP+%b-fLzd=O5yGT@poHyMtZ!^G zJG;bYr9!cg!}olmSe*=__?Q06$G`OF-;gMv*IDUux%?}sRO&-n*Zp%LIHJ{8EX$Qr zy|ffFQ2>f0hKQa(PHDm7e2vo1EV-OZ6vbGn#K%OdWZzarAzCSF3f4O@fBDJ+v*RU> z?&)W739h_!jK@zcLUEYG2geB8Z93g9Dc7bi=aWzSRGTdt%?`2D4D{t_2g#aQK9^>= zzraW_OCgh(?gmj}U~8BrTE;kz&G5(ohN)RzT;|-F88U?oGL@rQuaj{+d=pxcB9MtK zVvHti1(bG;^0pt?&lmsvBtb_Jg$mym)PiIdk+Txc9ZS%N6zy1H`W7GiZ>Je5oW=A^ ztYim=u1*&IO#wkK%GK=24ceii8Yv1E{L{Biap(2|v&#*B=h5?Au7)=PZiWU++<*Hd z`v(jbXRh$VT$7!*-^J~B>_){Q8|4k8ROIq`9M`7Z?Xq+wu`RJIlWZmpLYxhQ`1gMQ z)5m`68=8UjdaQQ4y*xB9@S;@e2txK$pS=V!rEkcfV;LhX6CsjbSI3&ZQi`#$JmJY& z;)i1zL_w5z@JmS)M)Z~Xh@*&3*g;5mZKlk*`3kp9^f5V{;RhbrNykX>;zEFDIb`f4 zVKM54_`b{JSRV+BupJ_m#P%F~&n263aUC0lAd<qe#>4sfQFEPhT30Uh&(!NbSl8O11Wl^uy`0jUR5zTQv`^jrq1)t4wM8-}6 zJ~}da%a!juWqW7^5`NfeXl`yD|&(5!Y8F7TuGP4MPDgEU$p z|MjuU9Gk1(=#72X<-Xgub6_mZ=E6KroU4)@-_AS!!2=AGveau08qE%#?^5h55=Jre zi>oZmu7K9~DG!1EQW&ZC{r;!E{Ab^k)Wg?pY29~S?IeWpRn~<`IE3z{w|=cN(3^GdEMCln(fg z$s!A(&vHYOas-Y}Y%zi$#&-mzVhW8ym{!lpA)!GG0X7!hAR>q*gZ(9J*QQc!aOUh) z)>qd_&rf18G?XBi{I_WtOjssYk{A5 zU>gRSKYivJkDc52stiBD(L+1AYu5m+l?7fseieUkj62_P7t`B@Xf)d_Ev?}=E2eyrk>X_`0uN3Jiy*iN!~D6eN? znHI>zrXq|rXV0v#e>%&S@gip~CJHTKnP{0fCu?C+ZML~34~2Y=!F(FgXrNmi_Kl75 z)`xcU@W;>a8=tts}5u_A;w0>*UjEMz)O5Xf%25%O|-qvqHuPBjb^C5+){!HEAV?5LlK$I~Fv; zn0>qYc>F|##ib?g+t*JsiV>!!8cMdOEsDOurD`H;7)S|L0)=BIEn(X3g=zHkIYFqg z?BttiB~aWxnQjo^Sr&fES&yRlKm6_|zx@7hHnv{Zz&A|eVXb*k zOKD*w?#HHS^`eV(FKo;}8v+?gA_Y;b**4wJ-hF*M^JIr^Hy{*=S5Op2$%|ajrs&3W z;+}_ME99Mrr)bw3oS11d`|%4rccRRe$q`gG&*#o8Ffp^izU>1{ZJ%acr3qt2+D)7n zgz8zc^!8HYP~)U6hKKu5+TiTDt6aQv4PgjINBW7S=JLhMoI8J&*-A_?ZD6_O@4sh==c*lw#UelSz#b;jiW4W! zaJ(F{_wXV1@81bpvADQ~ZCm8~iUN$va6N~#=dDI@_yG|(zx@ZFeSY)x zfGxr6yvE1Jw;MwI2ekSTde#-!ql=Q^mOz;%z6{8e7s+@AKlrZgg!MX)UbH#W%wR=L zVx>VSY%Ot2Nfb*KD;*pep<>0vK#F(XG0s5NJ1 zhl~$a$|vZA_)gMq`;JMotBI8&pEemx*&qx$osiMI#d=dRHs)~0fkB>rW(}obu@c}K zg6$=jnQ}lgh{Zc;LFj%XNnYWtjLXBv)C&6ma{lEIX%i zJh|lY7iU8M3t8razgI7Yd`Lmoh;WQWYESoO)}XGLcqE6SD3lB!0^xj0=RH#feV+HSZ#&a zJqqw``wQHA*A_nXrx!7l#I=niQ7}&24h$0}i%E*hdNU#n6}D+nDrib2hs_m*G&J?L zB#1Q=c?;XnT-=C~cNvv<-)shoMx0D$>urhFuy;$2yQhn!ZNagN6<(OFV;Rs^U|@1| z{{%;O^A2@IJ;y`)D-VRBKJrsWgSYJk?s0E0^b4TV2O-lb_en`aO1v z_x|1|Uaq|!@npVHfM2cG=W4b3NAiW-3qptyfu6elG; z+bvt@+p>j=>k%(Me}YU{VR~|aj+w^JWVw8Kmd77|fglPQ94xWAT;cdD=eanuP7q6c z$H2A(v4*~sMZ4Z)aV?-8Ci(#1Gze584Tz;c8<24X^|tC+^%-1R4mo$Z!(iS{q|Sk& z5+ux*XF|2BXa$N+oLD(VK(!@lM4H`WS^oZ=qwE<@Gqc*@(N~t4-3*9&%O-oKC-||q z?dHgs$;{lIILm>d89S<~CLy<4OIy_E63SQvORBvW1?Yj%@^;4u5*GP2?3A z>q}8-bXnhQ5`^K6-@Ma}sJ27$NHSVe@&zM#i=ojhYa-9WrX(BJ8S)h4V%Sqs-;A7dUa^67@!iVFI>6s1g?gsUhbI zg07?;LON|GdjNi7g5?N})X<4FwksHM4T4Y+n+93i1fi&R6~1GlFllxY<|yq797C|t zl1Qy_EQ4yGSZOGx`h4DgXq54S&6%s4Jau-Rawj1RxA5km~T|zSE|*s zo7L(EO8up_5ayVnXPO56Z?yStWU;8-SsVG^1q zZDG;zGE|HlDL=)o@dAFS#7Yz97uL|#4NATsHa+Sc$@D}&2M+G$@}}bHXHHVNa*=~m z1#UgK2P-$g!t4@P%Jn29*-CUTQVC2$V4L8&299mem5C!+f7&3761K%OjO1ak4J-uJ zt|C@~v}@1|B=s=4(X}#AKoCiUDQEx`9{Id8y5K2Yjd;uTy=Bv{lkU)rrWN+Q)$@0E6*K=hdIBd zxU|qD3cGZ>0j_P4OMAGE*_%?Dq&$aGE=7MS%V2+wQZCIv-XoWCle{gzpsy_ zdQ5qF6;)j)@0moVhhBU;pk;#-4csr8n=9mnO!t=stSyC>B@2M;R_ST)bBQrPGV8<7v;jN5-0FJIV6$U7KPyMKKG^=-CIj$r2dsI)__ox6-3HYt|!v;rs_tM5vJ=P zO!JIF|Fe&M{*|A9?b6EZ8xb$xGQbB|ki4)xt1oW7000dzNklMl`K1>*yraZ}-*FE+ zZ`;eZkrHbw8!T>iaHRsnNS3xuLEbf3+KdQ;fRTdWxl0XHCnlRVX-A5BsId%#IM#$Q ziG#C%AX2Qh6$3ekLtBgN9?G&&?efU0OO#t3I$gjtx%<#gzU$s;b`>NmGuODV)FeGI z#h!h;$Yorb^(Hb_^yO3Z_ZQfx)Hw0#S=P%ngk@nl_B8}Q^Px{2`|(p3m(IPBu_E{u zulw)6-+Jn)r(%HdzVzF)Vf+iF)H`J_F}=T#VW5=5vu%PB2QO+8S?gl;P0< zJl7%$W8xs9zm#KiY=COL$=uv3Yikv}l!s~Cv|63_`cd)U{?SuUb-xvG@huPhzpBRi zvkwWae_o;QiQ*X7br|f+QOakrO`~UKW#gCu5ex40HjYS^P%Yag?K`-Z-7|&M^fXPg0=8cig)he{h(JPLt23=*y;f_1rv9KXD8{sBzEj+qvUScS8RJXD`n3 z`A47OrE_y=V9#)hU;nv#dHcH#A;!kREpX|?EbspQU+45pg^Xj8wi3&bwWh?e1xI$4 z7|S_Cf#k{48{B!Iz~mO6-~8kP(-VW-d)roa^_whTxyre@D*5p#rgv>4owBIcT5Q&u z4D=V-HZerI-DPFH%G|jb@T0%-ZdeV_ z-Y_CH0QNLb{ORxU;Je>P!7?y}q8`D)$vkh`*-x_-aD1lBm2!t#kEz|irNGqoE!;AZ zBUoMG((F1aQ(|JrR>p=)v|Alotqz`RlgnrDe4j83Ie%d;u~sw%QmQXlw)yWq{HbFv ze=DB7`Rxq+Mkjne?|WY`OmVAe8e76Brq*oJYKK^+f#)P%JW6Q{EfA)WSPp7%91B|{ zwuQ}3L>NTum>eQi8sbVhWOaTCSze}?_lQlGS~Fnp_CdDqndX(*2Cu&O8l$4dp20g~ZzqtIZdiLMezz3*zg2j3}{DWM^dCfLN)-;VB-A+ig(WcW4 zF%1LXcN2RJnFM7>sgSY8w#`H|CzAZEW}}1WnC#v)j*%;IdAZ4%mrrAMYD|ol*bFpU z#T+>_Md0Rn;@CBsOLI)+pb><8^pUf?^w>EXv&*zDU!s_`@w_T0|NDRE$&(EZPWSVZ zZ{NZ4dXo=-@hY#acj!e6aOZ7PeBayl(=Xbbd-XLID_sg(r?_SB4vIOC%4Us7N(#js z>2!)%O0LbWFu$;dVVc;s6-BZ9fNO{!_`^qzJ^QVG?t+{3H8s(f*{clwvs&?^k(8LG zL9vi!Y_Lcn?e`MalgJ{+wa8_B9Lr4p-Y|Mj51MSo#rHkVU0&w&@skwIkfU!tfIl?G zT0La2m?4&e7hk?aXJw9}6XQ58?OGeF*!V>Tac!Hy{v0FyMRFM*WhjJF zxUNmwcX3P;!!mpMTuC}(GS2sDb|RjC;T#*Yv)r|Jhyw?Au@JaO;V@K4v)PJx>6Nq8 z7v`B5@No^1$PY3eS64&MUtXt>H95Z2MUoi64itRuy8RXojb~V2T;$aGMXbUAw;jBN zQYp*w@&@g0NFkr5R4fom$@=;x<#G+rbMZV|c019ByFv7UkN@SX$G_dq_a^ZFn%Xj$ z{TZS7k8vc;NX7V`!^l7%V?zae&moRt9LFS;@-Rr&939ufv8`Sby2ddLav7H^^A#?f zyTTw1c1;dY+&aZd;Nbf%`IOCX{r+buZ?@PumZ2NM?0ORyxbM&~g^>wPotxv@a)rsQ zLwv`9am?l>=P%CFuu^Q@zKyA^Lv(|HZZ{^A^|39JAdINi+mtIcNSrIQ<2b)#IqJP1 z{P+vkzFp7tCh-3z?axqtO2+bkvkdXmv6MzACE1k6_(+M-fkNWTZy5Nlm26?5@mz;g z%Ed4fi9*QE-`OTQyA!DbzzZFFXr<3Ypiu(bk{UnM*E3_h|Ow?blRa*%!6T2t+iNM+CVFf zWgB1^&!FR<_@mFfeE!@0OwF6H{_CsO3N{;^@C${k@vvc9+a1f=+37~Cm+Q2X`-N`~U}z9AIp?NTc4O-3{q0X36E!RBBDG z&8|?Zw=gUN!{9uo_=OLD`o*6*adCO$=84_}{@?Neh^w_$__4faKV#X}plKRAYRwMi zYLj*+K$rsG_po|#qG1$a^yp9-Cdn#NL!%X78L)Nh5S7^GnNtgFu5Yk)I8Vkm$v6fX z-(sjgO{Ed@#7k?OxwOXW`~r31GroH_yQa6$sMV=%HppdD3=R~~N;7k9h54m2mSti& zc3HyDJ^biP|LEj}rQ}hvlU*k&>9Ug_PpA9WVODKl;>(>dlk63H)zJ zjSpsiQXt+VrRu+KaoCqjGtifzuaLz{Idt1yTAh$?tmuX@jdquEwN1O-Va$-!I*PPs zl65pYCv!Y>xX5NhaE`6WC}etkfPwxZE9;wFnO&mWjfkTd!xZOi%lY|_eD3%of5rLg zo2PTL$N#!jy%ioG_H!S^6>-LQ4``{qO1(vSvq_`b!8R>M28(!}L${j(hyXeoD%q^@@skZQaA7Kb0DL-Yo=8u2m z&tEM6HD`SD#=i;tZ)_DjZ!(=Wf6+9=Kh|2)4kB#RWY^>{lVknZj!m-@QfstnbwZj! zOc=!s4iwnCbAr5UQduuEzqCOoj42i~r2N!rrS$*#@Mn*G{N^Wo6Zo&|njX&Vk=pt< zTBsimqnI#~6tgL|Z5d$u)*)QiV|}BBZ3=eZvXyMcV{UGhGv{Xs!w4_sBBfe$O#2r; z`SfeQd-D^$3H&!y?buQ}5=GI!(dh3A!iY#pMg|Jpx?`MuJGatT%&=ara{1~q3(I9Z z-^H-*eulBl(A)c+(V^8b|X^!`X|45>Xn literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/spritesheet/spritesheet.json b/packages/assets/test/assets/spritesheet/spritesheet.json new file mode 100644 index 00000000000..2b1d2609fdd --- /dev/null +++ b/packages/assets/test/assets/spritesheet/spritesheet.json @@ -0,0 +1,55 @@ +{ + "frames": { + "pic-sensei.jpg": { + "frame": { + "x": 1, + "y": 1, + "w": 125, + "h": 125 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 125, + "h": 125 + }, + "sourceSize": { + "w": 125, + "h": 125 + } + }, + "bunny.png": { + "frame": { + "x": 127, + "y": 1, + "w": 7, + "h": 10 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 7, + "h": 10 + }, + "sourceSize": { + "w": 7, + "h": 10 + } + } + }, + "meta": { + "app": "http://github.com/odrick/free-tex-packer-core", + "version": "0.3.4", + "image": "spritesheet.png", + "format": "RGBA8888", + "size": { + "w": 134, + "h": 126 + }, + "scale": 1 + } +} \ No newline at end of file diff --git a/packages/assets/test/assets/spritesheet/spritesheet.png b/packages/assets/test/assets/spritesheet/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..16a05ed0aed5e6514c77b37294d316fee70c25c8 GIT binary patch literal 3463 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 j`KEnm7wCet4TRSzKBpUn=T(v4| literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/textures/profile-abel@0.5x.webp b/packages/assets/test/assets/textures/profile-abel@0.5x.webp new file mode 100644 index 0000000000000000000000000000000000000000..a9c370a3d257deab8f53a1b265d1bd72646121df GIT binary patch literal 2082 zcmV+-2;KKmNk&E*2mkHTi;}#x}MHowC>NLcctHvvO5@7%}fT6ERzx+iae`iD#xDBK8ax!KJSRn z$ygyKKxe}LWxW!=9^tlSvbbpAWPyb-c%%_~3zYEXAOQZuMfG`8Z!-A9G;5h5%GKcV zuC8siomdcoFF+vBMuP#9BC)gwUs;RMPbvt8g*bnqy`3ufVMgedQkP5>U%B%C09#5+MyUDyK! zzXo5VFaTjd3!MMsy4X~@o%zs0ebN?W2y10S6fEBuO$V!<)tZ4*F{(kn_El?*uAOVf z5|K{!W;F(Ra?_g}BSGh;i^gwqlSze8qo=v!R7_l*%(F5hR$XnCv->FrQoIFV>ZDyMZio0Ki<20L&=vG*1P8vQiY=HApIIY1l%&`IY~%L zFod>QgM{TaXQH-oelaKESe2{(xnn$z7$DZie1uG+@{B*08Vl+{w}+S_w06X+|Ty(63!P&*6z)zz1N_5mSi~ z$rf^FmT;3o#w#P^=p&FTfvEjSz;=JxVlqwJ+my5Sy3MQ4g+?tLitQdS&Eq@ad z7k82Q(yj6J4c!PZ87yCTO}DaYLS0#K>}B<7^v_x|E?@@Eht%gFOe{4{XMLXzZ&DewQ@zZJEx?mtKjQ=nNzRotbo2+7p4iXK#sVc8&(5%A~iy>>D2)Pm5A0Al>O1+ zgIXT_ywBhTm{sd^2@Sx9mH^UX76X>DZI@%q38NW!!PVAJNgc*6YlYfkCF+HvsuCQ} zX5^!a#usuk%Gd|_pJ7{UC#pE>QQ>}+1MFWlg~c!Tt<*cO_koFcfBpflwmP#p#S2oG zKL@=DuhQw9@KB8%3fZC%}a@bhF*J)BuD=Wa|eH^;P4E0SI%;~BMS-c)Gt)!x8 zpH0w%%4E6;^EYp`vsUaMMG07iEBExo9P&~cB`oYUBmjj#^fUU#u&`;csUaE;9k>5^ zU9iD~BsJS8UAwJA=mnQX{iv7S29ar^nCa|rdUP7BSD7ZY9*Hi5!to?*)6V8FCprd| zf$J9Qe_lQd!aa83?4upp`H;f2jK(xArpQ5qjW#9}udEo-f!NAH9T=wr>W{>Pd0>-D z3R-uICoc+es-NaMQ1gicD}_+Q&KG;4N3@Bels9u48}%gX9EUBO?Ur!V&5qo%g%)ii z?OpUT^>vAT(NGci?82yaMKy0Cv36B4 zV9HM6rF=;QuY2P(E+UD@v7Ysi&Z0iL6=MLDKIGq z9zbH$0R?j2dy8@Y33eMF2>G_ccZ$ttI$=hB{QvFgWw6Njc99Zp6`^LJ`#tNSjeQ+o zFo-iF9($uS?>mp5o^9HhvDUKb^7FPH3rP%)asg*l)6h#i#l`JhqH`XM(2&l-@|l*h zWbcp!qllVUYip<*rARQt1oy6yW$dE6>08yYiGxvb+sA8nB5&@TLA*J+5g+?3SC%zU zvt48yqBbfSBBZYmW4eNvCOMxgP62KtqVwINId0Tx%RzCq1f-Y~$r8uEf|i=iuRfquq3A!) zF2w@J{HaKp6EX8}oQiTNAv?^J5tq7O|V5 MX}S^aurpu)09On7LI3~& literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/textures/profile-abel@2x.jpg b/packages/assets/test/assets/textures/profile-abel@2x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4624b746ac3371ae68d4d85219a58d0056c607ce GIT binary patch literal 25571 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 literal 0 HcmV?d00001 diff --git a/packages/assets/test/assets/textures/profile-abel@2x.webp b/packages/assets/test/assets/textures/profile-abel@2x.webp new file mode 100644 index 0000000000000000000000000000000000000000..2d9789607613296c4c028b4bcffa3c5cef6b3192 GIT binary patch literal 20830 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 literal 0 HcmV?d00001 diff --git a/packages/assets/test/cache.tests.ts b/packages/assets/test/cache.tests.ts new file mode 100644 index 00000000000..bfbdb976dbc --- /dev/null +++ b/packages/assets/test/cache.tests.ts @@ -0,0 +1,82 @@ +import type { CacheParser } from '@pixi/assets'; +import { Cache } from '@pixi/assets'; + +const testParser = { + test: (asset: string) => typeof asset === 'string', + getCacheableAssets: (keys: string[], asset: string) => + { + const out: Record = {}; + + keys.forEach((key) => + { + out[key] = `${asset}-${key}`; + }); + + return out; + } +}as CacheParser; + +describe('Cache', () => +{ + beforeEach(() => + { + Cache.reset(); + Cache['_parsers'] = []; + }); + + it('should process a custom parsers correctly', () => + { + Cache['_parsers'].push(testParser); + + Cache.set('test', 'hello'); + + const out = Cache.get('test'); + + expect(out).toBe('hello-test'); + }); + + it('should process multiple keys with a custom parser correctly', () => + { + Cache['_parsers'].push(testParser); + + Cache.set(['test', 'chicken'], 'hello'); + + const out = Cache.get('test'); + + expect(out).toBe('hello-test'); + + const chicken = Cache.get('chicken'); + + expect(chicken).toBe('hello-chicken'); + }); + + it('should remove keys with a custom parsers correctly', () => + { + Cache['_parsers'].push(testParser); + + Cache.set('test', 'hello'); + + Cache.remove('test'); + + const out = Cache.get('test'); + + expect(out).toBe(undefined); + }); + + it('should remove multiple keys with a custom parser correctly', () => + { + Cache['_parsers'].push(testParser); + + Cache.set(['test', 'chicken'], 'hello'); + + Cache.remove('test'); + + const out = Cache.get('test'); + + expect(out).toBe(undefined); + + const chicken = Cache.get('chicken'); + + expect(chicken).toBe(undefined); + }); +}); diff --git a/packages/assets/test/loader.tests.ts b/packages/assets/test/loader.tests.ts new file mode 100644 index 00000000000..2db0de00a30 --- /dev/null +++ b/packages/assets/test/loader.tests.ts @@ -0,0 +1,229 @@ +import { Texture } from '@pixi/core'; + +import type { LoaderParser } from '@pixi/assets'; +import { Cache, loadJson, loadSVG, loadTextures, loadWebFont } from '@pixi/assets'; +import { Loader } from '../src/loader/Loader'; + +describe('Loader', () => +{ + const serverPath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/assets/test/assets/` + : 'http://localhost:8080/assets/test/assets/'; + + beforeEach(() => + { + Cache.reset(); + }); + + it('should load a single image', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadTextures); + + const texture: Texture = await loader.load(`${serverPath}textures/bunny.png`); + + expect(texture.baseTexture.valid).toBe(true); + expect(texture.width).toBe(26); + expect(texture.height).toBe(37); + }); + + it('should load an svg', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadSVG); + + const texture: Texture = await loader.load(`${serverPath}svg/logo.svg`); + + expect(texture.baseTexture.valid).toBe(true); + expect(texture.width).toBe(512); + expect(texture.height).toBe(512); + }); + + it('should allow setting SVG width/height through metadata', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadSVG); + + const texture: Texture = await loader.load({ + data: { + resourceOptions: { + width: 128, + height: 256, + } + }, + src: `${serverPath}svg/logo.svg`, + }); + + const { width, height } = texture.baseTexture; + + expect(width).toEqual(128); + expect(height).toEqual(256); + }); + + it('should load a single image one after multiple loads', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadTextures); + + const texturesPromises = []; + + for (let i = 0; i < 10; i++) + { + texturesPromises.push(loader.load(`${serverPath}textures/bunny.png`)); + } + + const textures = await Promise.all(texturesPromises); + + const ogTexture = textures[0]; + + textures.forEach((texture) => + { + expect(texture).toBe(ogTexture); + }); + }); + + it('should load multiple images', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadTextures); + + const assetsUrls = [`${serverPath}textures/bunny.png`, `${serverPath}textures/bunny-2.png`]; + + const textures = await loader.load(assetsUrls); + + expect(textures[`${serverPath}textures/bunny.png`]).toBeInstanceOf(Texture); + expect(textures[`${serverPath}textures/bunny-2.png`]).toBeInstanceOf(Texture); + }); + + it('should load json file', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadJson); + + const json = await loader.load(`${serverPath}json/test.json`); + + expect(json).toEqual({ + testNumber: 23, + testString: 'Test String 23', + }); + }); + + it('should load a web font', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadWebFont); + + const font = await loader.load(`${serverPath}fonts/outfit.woff2`); + + let foundFont = false; + + document.fonts.forEach((f: FontFace) => + { + if (f.family === 'Outfit') + { + foundFont = true; + } + }); + + document.fonts.delete(font); + + expect(foundFont).toBe(true); + }); + + it('should load a web font with custom attributes', async () => + { + const loader = new Loader(); + + document.fonts.clear(); + loader['_parsers'].push(loadWebFont); + + const font = await loader.load({ + data: { + family: 'Overridden', + style: 'italic', + weights: ['normal'], + }, + src: `${serverPath}fonts/outfit.woff2`, + }); + + let count = 0; + + document.fonts.forEach((f: FontFace) => + { + count++; + expect(f.family).toBe('Overridden'); + expect(f.weight).toBe('normal'); + expect(f.style).toBe('italic'); + }); + + document.fonts.delete(font); + + expect(count).toBe(1); + }); + + it('should load with metaData', async () => + { + const loader = new Loader(); + + loader['_parsers'].push({ + test: () => true, + load: async (url, options) => + url + options.data.whatever, + } as LoaderParser); + + const sillyID: string = await loader.load({ + src: `${serverPath}textures/bunny.png`, + data: { whatever: 23 }, + }); + + expect(sillyID).toBe(`${serverPath}textures/bunny.png23`); + }); + + it('should unload a texture', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadTextures); + + const texture: Texture = await loader.load(`${serverPath}textures/bunny.png`); + + expect(texture.baseTexture.destroyed).toBe(false); + + const baseTexture = texture.baseTexture; + + await loader.unload(`${serverPath}textures/bunny.png`); + + expect(texture.baseTexture).toBe(null); + expect(baseTexture.destroyed).toBe(true); + }); + + it('should unload a web font', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadWebFont); + + await loader.load(`${serverPath}fonts/outfit.woff2`); + + await loader.unload(`${serverPath}fonts/outfit.woff2`); + + let foundFont = false; + + document.fonts.forEach((f: FontFace) => + { + if (f.family === 'Outfit') + { + foundFont = true; + } + }); + + expect(foundFont).toBe(false); + }); +}); diff --git a/packages/assets/test/resolver.tests.ts b/packages/assets/test/resolver.tests.ts new file mode 100644 index 00000000000..b5710a416e0 --- /dev/null +++ b/packages/assets/test/resolver.tests.ts @@ -0,0 +1,444 @@ +import { resolveTextureUrl } from '@pixi/assets'; +import { Resolver } from '../src/resolver/Resolver'; +import { manifest } from './sampleManifest'; + +describe('Resolver', () => +{ + it('should resolve asset', () => + { + const resolver = new Resolver(); + + [ + { + preferOrder: { + priority: ['resolution', 'format'], + params: { + format: ['png', 'webp'], + resolution: [2, 1], + }, + }, + expected: 'my-image@2x.png', + }, + { + preferOrder: { + params: { + resolution: [1], + format: ['png', 'webp'], + }, + priority: ['resolution', 'format'], + }, + expected: 'my-image.png', + }, + { + preferOrder: { + params: { + resolution: [1], + format: ['webp', 'png'], + }, + priority: ['resolution', 'format'], + }, + expected: 'my-image.webp', + }, + { + preferOrder: { + params: { + resolution: [2, 1], + format: ['webp', 'png'], + }, + priority: ['format', 'resolution'], + }, + expected: 'my-image.webp', + }, + { + preferOrder: { + params: { + resolution: [2, 1], + format: ['webp', 'png'], + }, + priority: ['resolution', 'format'], + }, + expected: 'my-image@2x.png', + }, + + ].forEach((testData, i) => + { + if (i !== 0) return; + + resolver.reset(); + + resolver.prefer(testData.preferOrder); + + resolver.add('test', [ + { + resolution: 1, + format: 'png', + src: 'my-image.png', + }, + { + resolution: 2, + format: 'png', + src: 'my-image@2x.png', + }, + { + resolution: 1, + format: 'webp', + src: 'my-image.webp', + }, + ]); + + const asset = resolver.resolveUrl('test'); + + expect(asset).toBe(testData.expected); + }); + }); + + it('should resolve the correct texture', () => + { + const resolver = new Resolver(); + + resolver.prefer({ + priority: ['resolution', 'format'], + params: { + format: ['jpg'], + resolution: [2], + }, + }); + + resolver['_parsers'].push(resolveTextureUrl); + + resolver.add('test', [ + 'profile-abel@0.5x.jpg', + 'profile-abel@2x.jpg', + 'profile-abel@0.5x.webp', + 'profile-abel@2x.webp', + ]); + + expect(resolver.resolveUrl('test')).toBe('profile-abel@2x.jpg'); + }); + + it('should resolve asset without priority', () => + { + const resolver = new Resolver(); + + [ + { + preferOrder: { + params: { + resolution: [2], + format: ['webp', 'png'], + }, + }, + expected: 'my-image@2x.png', + }, + { + preferOrder: { + params: { + format: ['webp', 'png'], + resolution: [2], + }, + }, + expected: 'my-image.webp', + }, + ].forEach((testData) => + { + resolver.reset(); + + resolver.add('test', [ + { + resolution: 1, + format: 'png', + src: 'my-image.png', + }, + { + resolution: 2, + format: 'png', + src: 'my-image@2x.png', + }, + { + resolution: 1, + format: 'webp', + src: 'my-image.webp', + }, + ]); + + resolver.prefer(testData.preferOrder); + + const asset = resolver.resolveUrl('test'); + + expect(asset).toBe(testData.expected); + }); + }); + + it('should be able to have resolve to a different string', () => + { + const resolver = new Resolver(); + + resolver.add('test', 'hello'); + + expect(resolver.resolveUrl('test')).toBe('hello'); + }); + + it('should be able to have multiple aliases', () => + { + const resolver = new Resolver(); + + resolver.prefer({ + params: { + resolution: [2, 1], + format: ['webp', 'png'], + }, + priority: ['resolution', 'format'], + }); + + resolver.add(['test', 'test-2', 'test-3'], [{ + resolution: 2, + format: 'png', + src: 'my-image.png', + }]); + + expect(resolver.resolveUrl('test')).toBe('my-image.png'); + expect(resolver.resolveUrl('test-2')).toBe('my-image.png'); + expect(resolver.resolveUrl('test-3')).toBe('my-image.png'); + }); + + it('should set base path correctly on urls', () => + { + const resolver = new Resolver(); + + resolver.basePath = 'http://localhost:8080/'; + + resolver.add('test', 'bunny.png'); + + expect(resolver.resolveUrl('test')).toBe('http://localhost:8080/bunny.png'); + }); + + it('should be able to have multiple preferences', () => + { + const resolver = new Resolver(); + + // check the params when adding! + resolver.prefer({ + params: { + format: ['ogg', 'mp3'], + }, + }); + + resolver.prefer({ + params: { + format: ['webp', 'png'], + resolution: [2, 1], + }, + }); + + resolver.add('test', [{ + resolution: 2, + format: 'png', + src: 'my-image.png', + }]); + + // TODO add default parser that just extracts file format + resolver.add('explode-sound', [ + `explode.mp3`, + `explode.ogg`, + ]); + + expect(resolver.resolveUrl('test')).toBe('my-image.png'); + expect(resolver.resolveUrl('explode-sound')).toBe('explode.ogg'); + }); + + it('should be able to parse strings', () => + { + const resolver = new Resolver(); + + resolver.prefer({ + priority: ['format'], + params: { + format: ['png', 'webp'], + }, + }); + + resolver.add('test', [ + 'my-image.webp', + 'my-image.png', + ]); + + expect(resolver.resolveUrl('test')).toBe('my-image.png'); + }); + + it('should be able to parse strings in a custom way', () => + { + const resolver = new Resolver(); + + resolver.prefer({ + priority: ['resolution', 'format'], + params: { + resolution: [2, 1], + format: ['webp', 'png'], + }, + }); + + resolver['_parsers'].push(resolveTextureUrl); + + resolver.add('test', [ + 'my-image@4x.webp', + 'my-image@2x.webp', + 'my-image@2x.png', + 'my-image.png', + ]); + + expect(resolver.resolveUrl('test')).toBe('my-image@2x.webp'); + }); + + it('should resolve multiple assets', () => + { + const resolver = new Resolver(); + + resolver.add('test', 'out1.png'); + resolver.add('test2', 'out2.png'); + resolver.add('test3', 'out4.png'); + + expect(resolver.resolve(['test', 'test2', 'test3'])).toEqual({ + test: { + alias: ['test'], + format: 'png', + src: 'out1.png', + }, + test2: { + alias: ['test2'], + format: 'png', + src: 'out2.png', + }, + test3: { + alias: ['test3'], + format: 'png', + src: 'out4.png', + }, + }); + + expect(resolver.resolveUrl(['test', 'test2', 'test3'])).toEqual({ + test: 'out1.png', + test2: 'out2.png', + test3: 'out4.png', + }); + }); + + it('should resolve a bundle id correctly', () => + { + const resolver = new Resolver(); + + resolver.prefer({ + params: { + resolution: [2, 1], + format: ['webp', 'png'], + }, + }); + + resolver.add('test', [ + { + resolution: 2, + format: 'webp', + src: 'my-spritesheet@2x.webp.json', + }, + { + resolution: 0.5, + format: 'webp', + src: 'my-spritesheet@0.5x.webp.json', + }, + { + resolution: 2, + format: 'png', + src: 'my-spritesheet@2x.png.json', + }, + { + resolution: 0.5, + format: 'png', + src: 'my-spritesheet@0.5x.png.json', + }, + ]); + + expect(resolver.resolveUrl('test')).toBe('my-spritesheet@2x.webp.json'); + }); + + it('should get multiple bundle ids correctly', () => + { + const resolver = new Resolver(); + + resolver.addManifest(manifest); + + const assets = resolver.resolveBundle(['default', 'level']); + + expect(assets.level).toEqual({ + image3: { + alias: ['image3'], + format: 'png', + resolution: 1, + src: 'chicken.png', + }, + }); + + expect(assets.default).toEqual({ + image1: { + alias: ['image1'], + format: 'png', + resolution: 1, + src: 'my-sprite@2x.png', + }, + levelData: { + alias: [ + 'levelData', + ], + format: 'json', + src: 'levelData.json', + }, + spriteSheet1: { + alias: ['spriteSheet1'], + format: 'png', + resolution: 1, + src: 'my-sprite-sheet.json', + }, + spriteSheet2: { + alias: ['spriteSheet2'], + format: 'png', + resolution: 1, + src: 'my-sprite-sheet-2.json', + }, + }); + }); + + it('should resolve a bundle correctly', () => + { + const resolver = new Resolver(); + + resolver.addManifest(manifest); + + const assets = resolver.resolveUrl(['image1', 'levelData', 'spriteSheet1', 'spriteSheet2']); + + expect(assets).toEqual({ + image1: 'my-sprite@2x.png', + levelData: 'levelData.json', + spriteSheet1: 'my-sprite-sheet.json', + spriteSheet2: 'my-sprite-sheet-2.json', + }); + }); + + it('should be able to have resolve with a single string with {} options', () => + { + const resolver = new Resolver(); + + resolver.add('test', 'my-image.{png, webp}'); + + expect(resolver.resolveUrl('test')).toBe('my-image.png'); + + resolver.reset(); + + resolver.add('test', 'my-image.{png,webp}'); + + resolver.prefer({ + params: { + format: ['webp', 'png'], + }, + }); + + expect(resolver.resolveUrl('test')).toBe('my-image.webp'); + }); +}); diff --git a/packages/assets/test/sampleManifest.ts b/packages/assets/test/sampleManifest.ts new file mode 100644 index 00000000000..f041aa1ed34 --- /dev/null +++ b/packages/assets/test/sampleManifest.ts @@ -0,0 +1,75 @@ +import type { ResolverManifest } from '../src/resolver/types'; + +export const manifest: ResolverManifest = { + bundles: [ + { + name: 'default', + assets: [ + { + name: 'image1', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite@2x.png', + }, + { + resolution: 2, + format: 'png', + src: 'my-image@2x.png', + }, + ], + }, + { + name: 'spriteSheet1', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite-sheet.json', + }, + { + resolution: 2, + format: 'png', + src: 'my-sprite-sheet@2x.json', + }, + ], + }, + { + name: `spriteSheet2`, + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite-sheet-2.json', + }, + ], + }, + { + name: 'levelData', + srcs: 'levelData.json', + }, + ], + }, + { + name: 'level', + assets: [ + { + name: 'image3', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'chicken.png', + }, + { + resolution: 2, + format: 'png', + src: 'chicken@2x.png', + }, + ], + }, + ], + }, + ], +}; diff --git a/packages/assets/test/sampleManifests.ts b/packages/assets/test/sampleManifests.ts new file mode 100644 index 00000000000..f041aa1ed34 --- /dev/null +++ b/packages/assets/test/sampleManifests.ts @@ -0,0 +1,75 @@ +import type { ResolverManifest } from '../src/resolver/types'; + +export const manifest: ResolverManifest = { + bundles: [ + { + name: 'default', + assets: [ + { + name: 'image1', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite@2x.png', + }, + { + resolution: 2, + format: 'png', + src: 'my-image@2x.png', + }, + ], + }, + { + name: 'spriteSheet1', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite-sheet.json', + }, + { + resolution: 2, + format: 'png', + src: 'my-sprite-sheet@2x.json', + }, + ], + }, + { + name: `spriteSheet2`, + srcs: [ + { + resolution: 1, + format: 'png', + src: 'my-sprite-sheet-2.json', + }, + ], + }, + { + name: 'levelData', + srcs: 'levelData.json', + }, + ], + }, + { + name: 'level', + assets: [ + { + name: 'image3', + srcs: [ + { + resolution: 1, + format: 'png', + src: 'chicken.png', + }, + { + resolution: 2, + format: 'png', + src: 'chicken@2x.png', + }, + ], + }, + ], + }, + ], +}; diff --git a/packages/assets/test/utils.tests.ts b/packages/assets/test/utils.tests.ts new file mode 100644 index 00000000000..976d9483743 --- /dev/null +++ b/packages/assets/test/utils.tests.ts @@ -0,0 +1,35 @@ +import { createStringVariations } from '@pixi/assets'; + +describe('Utils', () => +{ + it('createStringVariations should parse correctly', () => + { + const out = createStringVariations('hell@{2,1,0.5}x.{png,webp,avif}'); + + expect(out).toEqual([ + 'hell@2x.png', + 'hell@2x.webp', + 'hell@2x.avif', + 'hell@1x.png', + 'hell@1x.webp', + 'hell@1x.avif', + 'hell@0.5x.png', + 'hell@0.5x.webp', + 'hell@0.5x.avif', + ]); + + const out2 = createStringVariations('name is {chicken,wolf,sheep}'); + + expect(out2).toEqual([ + 'name is chicken', + 'name is wolf', + 'name is sheep', + ]); + + const out3 = createStringVariations('hell@2x.png'); + + expect(out3).toEqual([ + 'hell@2x.png', + ]); + }); +}); diff --git a/packages/basis/README.md b/packages/basis/README.md index 7b3b8a75d5f..ba91c85768c 100644 --- a/packages/basis/README.md +++ b/packages/basis/README.md @@ -11,8 +11,5 @@ npm install @pixi/core ## Usage ```js -import { BasisLoader } from '@pixi/basis'; -import { Loader } from '@pixi/loaders'; - -Loader.registerPlugin(BasisLoader); +import '@pixi/basis'; ``` diff --git a/packages/basis/package.json b/packages/basis/package.json index 76ddf536f65..08a96aef88d 100644 --- a/packages/basis/package.json +++ b/packages/basis/package.json @@ -1,6 +1,6 @@ { "name": "@pixi/basis", - "version": "6.3.0", + "version": "7.0.0-alpha", "description": "Loader for the *.basis supercompressed texture file format. This package also ships with the transcoder!", "keywords": [ "basisu", @@ -12,8 +12,20 @@ "homepage": "https://github.com/pixijs/pixi.js#readme", "license": "MIT", "main": "dist/cjs/basis.js", - "module": "dist/esm/basis.js", - "bundle": "dist/browser/basis.js", + "module": "dist/esm/basis.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/basis.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/basis.js" + } + } + }, "publishConfig": { "access": "public" }, @@ -32,11 +44,9 @@ "bugs": { "url": "https://github.com/pixijs/pixi.js/issues" }, - "peerDependencies": { - "@pixi/compressed-textures": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/runner": "6.3.0" - } + "pixiRequirements": [ + "@pixi/assets", + "@pixi/compressed-textures", + "@pixi/core" + ] } diff --git a/packages/basis/src/Basis.ts b/packages/basis/src/Basis.ts index a673e1ad09d..e1513d29eb6 100644 --- a/packages/basis/src/Basis.ts +++ b/packages/basis/src/Basis.ts @@ -1,15 +1,15 @@ -import { TYPES } from '@pixi/constants'; +import { TYPES } from '@pixi/core'; import { INTERNAL_FORMATS } from '@pixi/compressed-textures'; /** * The transcoding formats provided by basis_universal. * * NOTE: Not all of these formats are supported on WebGL! - * * @ignore */ -/* eslint-disable camelcase */ -export enum BASIS_FORMATS { +/* eslint-disable camelcase, @typescript-eslint/indent */ +export enum BASIS_FORMATS +{ cTFETC1 = 0, cTFETC2 = 1, cTFBC1 = 2, @@ -27,11 +27,10 @@ export enum BASIS_FORMATS { cTFBGR565 = 15, cTFRGBA4444 = 16, } -/* eslint-enable camelcase */ +/* eslint-enable camelcase, @typescript-eslint/indent */ /** * Maps {@link BASIS_FORMATS} to {@link PIXI.INTERNAL_FORMATS} - * * @ignore */ export const BASIS_FORMAT_TO_INTERNAL_FORMAT: { [id: number]: INTERNAL_FORMATS } = { @@ -41,7 +40,7 @@ export const BASIS_FORMAT_TO_INTERNAL_FORMAT: { [id: number]: INTERNAL_FORMATS } [BASIS_FORMATS.cTFPVRTC1_4_RGB]: INTERNAL_FORMATS.COMPRESSED_RGB_PVRTC_4BPPV1_IMG, [BASIS_FORMATS.cTFPVRTC1_4_RGBA]: INTERNAL_FORMATS.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, [BASIS_FORMATS.cTFATC_RGB]: INTERNAL_FORMATS.COMPRESSED_RGB_ATC_WEBGL, - [BASIS_FORMATS.cTFASTC_4x4]: INTERNAL_FORMATS.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL + [BASIS_FORMATS.cTFASTC_4x4]: INTERNAL_FORMATS.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL, }; /** @@ -50,18 +49,16 @@ export const BASIS_FORMAT_TO_INTERNAL_FORMAT: { [id: number]: INTERNAL_FORMATS } * * NOTE: {@link BASIS_FORMATS.cTFBGR565} is not supported, while {@link BASIS_FORMATS.cTFRGBA4444} is not implemented by * [at]pixi/basis. - * * @ignore */ export const BASIS_FORMAT_TO_TYPE: { [id: number]: TYPES } = { [BASIS_FORMATS.cTFRGBA32]: TYPES.UNSIGNED_BYTE, [BASIS_FORMATS.cTFRGB565]: TYPES.UNSIGNED_SHORT_5_6_5, - [BASIS_FORMATS.cTFRGBA4444]: TYPES.UNSIGNED_SHORT_4_4_4_4 + [BASIS_FORMATS.cTFRGBA4444]: TYPES.UNSIGNED_SHORT_4_4_4_4, }; /** * Maps {@link PIXI.INTERNAL_FORMATS} to {@link BASIS_FORMATS} - * * @ignore */ export const INTERNAL_FORMAT_TO_BASIS_FORMAT: { [id: number]: number } @@ -76,18 +73,16 @@ export const INTERNAL_FORMAT_TO_BASIS_FORMAT: { [id: number]: number } /** * Enumerates the basis formats with alpha components - * * @ignore */ export const BASIS_FORMATS_ALPHA: { [id: number]: boolean } = { [BASIS_FORMATS.cTFBC3]: true, [BASIS_FORMATS.cTFPVRTC1_4_RGBA]: true, - [BASIS_FORMATS.cTFASTC_4x4]: true + [BASIS_FORMATS.cTFASTC_4x4]: true, }; /** * Binding to C++ {@code BasisFile} wrapper class. - * * @see https://github.com/BinomialLLC/basis_universal/blob/master/webgl/transcoder/basis_wrappers.cpp * @private */ @@ -117,7 +112,6 @@ export declare class BasisFile // Missing typings? - https://github.com/microsoft/TypeScript/issues/39655 /** * Compressed texture extensions relevant to the formats into which Basis can decompress into. - * * @ignore */ /* eslint-disable camelcase */ @@ -134,7 +128,6 @@ export type BasisTextureExtensions = { /** * API provided by basis_universal WebGL library. - * * @ignore */ export type BasisBinding = { @@ -144,7 +137,6 @@ export type BasisBinding = { /** * Binding to basis_universal WebGL library. - * * @see https://github.com/BinomialLLC/basis_universal/blob/master/webgl/transcoder/build/basis_transcoder.js * @ignore */ diff --git a/packages/basis/src/TranscoderWorker.ts b/packages/basis/src/TranscoderWorker.ts index 6cb48c5ee13..2ce861269e7 100644 --- a/packages/basis/src/TranscoderWorker.ts +++ b/packages/basis/src/TranscoderWorker.ts @@ -1,14 +1,13 @@ -import { Runner } from '@pixi/runner'; -import { BASIS_FORMATS } from './Basis'; -import { ITranscodeResponse, TranscoderWorkerWrapper } from './TranscoderWorkerWrapper'; +import type { BASIS_FORMATS } from './Basis'; +import type { ITranscodeResponse } from './TranscoderWorkerWrapper'; +import { TranscoderWorkerWrapper } from './TranscoderWorkerWrapper'; /** * Worker class for transcoding *.basis files in background threads. * * To enable asynchronous transcoding, you need to provide the URL to the basis_universal transcoding * library. - * - * @memberof PIXI.BasisLoader + * @memberof PIXI.BasisParser */ export class TranscoderWorker { @@ -22,7 +21,13 @@ export class TranscoderWorker static jsSource: string; static wasmSource: ArrayBuffer; - public static onTranscoderInitialized = new Runner('onTranscoderInitialized'); + private static _onTranscoderInitializedResolve: () => void; + + /** a promise that when reslved means the transcoder is ready to be used */ + public static onTranscoderInitialized = new Promise((resolve) => + { + TranscoderWorker._onTranscoderInitializedResolve = resolve; + }); isInit: boolean; load: number; @@ -124,7 +129,6 @@ export class TranscoderWorker /** * Handles responses from the web-worker - * * @param e - a message event containing the transcoded response */ protected onMessage = (e: MessageEvent): void => @@ -162,7 +166,6 @@ export class TranscoderWorker /** * Loads the transcoder source code - * * @param jsURL - URL to the javascript basis transcoder * @param wasmURL - URL to the wasm basis transcoder * @returns A promise that resolves when both the js and wasm transcoders have been loaded. @@ -177,8 +180,9 @@ export class TranscoderWorker .then((arrayBuffer: ArrayBuffer) => { TranscoderWorker.wasmSource = arrayBuffer; }); return Promise.all([jsPromise, wasmPromise]).then((data) => + { - TranscoderWorker.onTranscoderInitialized.emit(); + this._onTranscoderInitializedResolve(); return data; }); @@ -186,7 +190,6 @@ export class TranscoderWorker /** * Set the transcoder source code directly - * * @param jsSource - source for the javascript basis transcoder * @param wasmSource - source for the wasm basis transcoder */ diff --git a/packages/basis/src/TranscoderWorkerWrapper.ts b/packages/basis/src/TranscoderWorkerWrapper.ts index e53dce4cbc9..0de27a9708f 100644 --- a/packages/basis/src/TranscoderWorkerWrapper.ts +++ b/packages/basis/src/TranscoderWorkerWrapper.ts @@ -4,7 +4,8 @@ import type { BASIS, BASIS_FORMATS, BasisBinding } from './Basis'; * Initialization message sent by the main thread. * @ignore */ -export interface IInitializeTranscoderMessage { +export interface IInitializeTranscoderMessage +{ wasmSource: ArrayBuffer; type: 'init'; } @@ -23,7 +24,8 @@ export interface ITranscodeMessage } /** @ignore */ -export interface ITranscodedImage { +export interface ITranscodedImage +{ imageID: number; levelArray: Array<{ levelID: number, @@ -39,7 +41,8 @@ export interface ITranscodedImage { * Response format for {@link TranscoderWorker}. * @ignore */ -export interface ITranscodeResponse { +export interface ITranscodeResponse +{ type: 'init' | 'transcode'; requestID?: number; success: boolean; @@ -57,8 +60,10 @@ export interface ITranscodeResponse { }>; } -declare global { - interface Window { +declare global +{ + interface Window + { BASIS: BASIS; } } @@ -70,7 +75,6 @@ declare global { * The transcoder worker responds to two types of messages: "init" and "transcode". You must always send the first "init" * {@link IInitializeTranscoderMessage} message with the WebAssembly binary; if the transcoder is successfully initialized, * the web-worker will respond by sending another {@link ITranscodeResponse} message with `success: true`. - * * @ignore */ export function TranscoderWorkerWrapper(): void diff --git a/packages/basis/src/index.ts b/packages/basis/src/index.ts index ffab2430aaa..789b8bf2f60 100644 --- a/packages/basis/src/index.ts +++ b/packages/basis/src/index.ts @@ -1,8 +1,4 @@ -import { Loader } from '@pixi/loaders'; -import { BasisLoader } from './BasisLoader'; - export * from './Basis'; -export * from './BasisLoader'; +export * from './loader'; +export * from './TranscoderWorker'; -// parse any BASIS supercompressed files into textures -Loader.registerPlugin(BasisLoader); diff --git a/packages/basis/src/BasisLoader.ts b/packages/basis/src/loader/BasisParser.ts similarity index 65% rename from packages/basis/src/BasisLoader.ts rename to packages/basis/src/loader/BasisParser.ts index 3ae3fb0b69b..0cf043f83b5 100644 --- a/packages/basis/src/BasisLoader.ts +++ b/packages/basis/src/loader/BasisParser.ts @@ -1,33 +1,20 @@ -import { TYPES, MIPMAP_MODES, ALPHA_MODES, FORMATS } from '@pixi/constants'; -import { BaseTexture, BufferResource, Texture } from '@pixi/core'; -import { CompressedTextureResource, INTERNAL_FORMATS } from '@pixi/compressed-textures'; +import { CompressedTextureResource } from '@pixi/compressed-textures'; +import { BufferResource, TYPES, settings } from '@pixi/core'; import { BASIS_FORMATS, - BASIS_FORMAT_TO_INTERNAL_FORMAT, - INTERNAL_FORMAT_TO_BASIS_FORMAT, BASIS_FORMATS_ALPHA, - BasisTextureExtensions, - BasisBinding, - BASIS_FORMAT_TO_TYPE -} from './Basis'; -import { TranscoderWorker } from './TranscoderWorker'; -import { LoaderResource } from '@pixi/loaders'; + BASIS_FORMAT_TO_INTERNAL_FORMAT, + INTERNAL_FORMAT_TO_BASIS_FORMAT +} from '../Basis'; +import { TranscoderWorker } from '../TranscoderWorker'; -import type { IResourceMetadata } from '@pixi/loaders'; -import type { CompressedLevelBuffer } from '@pixi/compressed-textures'; +import type { BasisBinding, BasisTextureExtensions } from '../Basis'; +import type { CompressedLevelBuffer, INTERNAL_FORMATS } from '@pixi/compressed-textures'; -type TranscodedResourcesArray = (Array | Array) & { +export type TranscodedResourcesArray = (Array | Array) & { basisFormat: BASIS_FORMATS }; -/** - * Result when calling registerCompressedTextures. - * @ignore - */ - type BasisTexturesResult = Pick; - -LoaderResource.setExtensionXhrType('basis', LoaderResource.XHR_RESPONSE_TYPE.BUFFER); - /** * Loader plugin for handling BASIS supercompressed texture files. * @@ -51,164 +38,59 @@ LoaderResource.setExtensionXhrType('basis', LoaderResource.XHR_RESPONSE_TYPE.BUF * * ```js * // Use this if you to use the default CDN url for @pixi/basis - * BasisLoader.loadTranscoder(); + * BasisParser.loadTranscoder(); * * // Use this if you want to serve the transcoder on your own - * BasisLoader.loadTranscoder('./basis_transcoder.js', './basis_transcoder.wasm'); + * BasisParser.loadTranscoder('./basis_transcoder.js', './basis_transcoder.wasm'); * ``` * * NOTE: This can only be used with web-workers. - * * @class * @memberof PIXI - * @implements PIXI.ILoaderPlugin + * @implements {PIXI.ILoaderPlugin} */ -export class BasisLoader +export class BasisParser { - private static basisBinding: BasisBinding; + public static basisBinding: BasisBinding; private static defaultRGBFormat: { basisFormat: BASIS_FORMATS, textureFormat: INTERNAL_FORMATS | TYPES }; private static defaultRGBAFormat: { basisFormat: BASIS_FORMATS, textureFormat: INTERNAL_FORMATS | TYPES }; private static fallbackMode = false; private static workerPool: TranscoderWorker[] = []; - /** - * Transcodes the *.basis data when the data is loaded. If the transcoder is not bound yet, it - * will hook transcoding to {@link BasisResource#onTranscoderInitialized}. - * - * @see PIXI.Loader.loaderMiddleware - * @param resource - loader resource that is checked to see if it is a basis file - * @param next - callback Function to call when done - */ - public static use(resource: LoaderResource, next: (...args: any[]) => void): void - { - if (resource.extension === 'basis' && resource.data) - { - if (!!BasisLoader.basisBinding || (!!BasisLoader.TranscoderWorker.wasmSource)) - { - BasisLoader.transcode(resource, next); - } - else - { - TranscoderWorker.onTranscoderInitialized.add(() => - { - BasisLoader.transcode(resource, next); - }); - } - } - else - { - next(); - } - } - /** * Runs transcoding and populates {@link imageArray}. It will run the transcoding in a web worker * if they are available. - * * @private */ - private static async transcode(resource: LoaderResource, next: (...args: any[]) => void): Promise + public static async transcode(arrayBuffer: ArrayBuffer): Promise { - try - { - const data: ArrayBuffer = resource.data; - let resources: TranscodedResourcesArray; - - if (typeof Worker !== 'undefined' && BasisLoader.TranscoderWorker.wasmSource) - { - resources = await BasisLoader.transcodeAsync(data); - } - else - { - resources = BasisLoader.transcodeSync(data); - } + let resources: TranscodedResourcesArray; - Object.assign(resource, BasisLoader.registerTextures( - resource.url, - resources, - resource.metadata - )); - } - catch (err) + if (typeof Worker !== 'undefined' && BasisParser.TranscoderWorker.wasmSource) { - next(err); - - return; + resources = await BasisParser.transcodeAsync(arrayBuffer); } - - next(); - } - - /** - * Creates textures and adds them to the texture cache - * @private - * @param url - url of the texture to be used as its ID for the texture cache - * @param resources - the transcoded resources - * @param metadata - resource metadata - */ - private static registerTextures( - url: string, - resources: TranscodedResourcesArray, - metadata: IResourceMetadata - ): BasisTexturesResult - { - const result: BasisTexturesResult = { - textures: {}, - texture: null, - }; - - if (!resources) + else { - return result; + resources = BasisParser.transcodeSync(arrayBuffer); } - // Should be a valid TYPES, FORMATS for uncompressed basis formats - const type: TYPES = BASIS_FORMAT_TO_TYPE[resources.basisFormat]; - const format: FORMATS = resources.basisFormat !== BASIS_FORMATS.cTFRGBA32 ? FORMATS.RGB : FORMATS.RGBA; - const resourceList = resources as Array; - - const textures = resourceList.map((resource) => - ( - new Texture(new BaseTexture(resource, Object.assign({ - mipmap: resource instanceof CompressedTextureResource && resource.levels > 1 - ? MIPMAP_MODES.ON_MANUAL - : MIPMAP_MODES.OFF, - alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, - type, - format - }, metadata))) - )); - - textures.forEach((texture: Texture, i: number) => - { - const { baseTexture } = texture; - const cacheID = `${url}-${i + 1}`; - - BaseTexture.addToCache(baseTexture, cacheID); - Texture.addToCache(texture, cacheID); - - if (i === 0) - { - BaseTexture.addToCache(baseTexture, url); - Texture.addToCache(texture, url); - result.texture = texture; - } - - result.textures[cacheID] = texture; - }); - - return result; + return resources; } /** * Finds a suitable worker for transcoding and sends a transcoding request - * * @private * @async */ - private static async transcodeAsync(arrayBuffer: ArrayBuffer): Promise + public static async transcodeAsync(arrayBuffer: ArrayBuffer): Promise { - const workerPool = BasisLoader.workerPool; + if (!BasisParser.defaultRGBAFormat && !BasisParser.defaultRGBFormat) + { + BasisParser.autoDetectFormats(); + } + + const workerPool = BasisParser.workerPool; let leastLoad = 0x10000000; let worker = null; @@ -235,8 +117,8 @@ export class BasisLoader const response = await worker.transcodeAsync( new Uint8Array(arrayBuffer), - BasisLoader.defaultRGBAFormat.basisFormat, - BasisLoader.defaultRGBFormat.basisFormat + BasisParser.defaultRGBAFormat.basisFormat, + BasisParser.defaultRGBFormat.basisFormat, ); const basisFormat = response.basisFormat; @@ -260,7 +142,7 @@ export class BasisLoader width: imageArray[i].width, height: imageArray[i].height, levelBuffers: imageArray[i].levelArray, - levels: imageArray[i].levelArray.length + levels: imageArray[i].levelArray.length, }); } } @@ -270,8 +152,8 @@ export class BasisLoader imageResources = imageArray.map((image) => new BufferResource( new Uint16Array(image.levelArray[0].levelBuffer.buffer), { width: image.width, - height: image.height - }) + height: image.height, + }), ) as TranscodedResourcesArray; } @@ -282,12 +164,16 @@ export class BasisLoader /** * Runs transcoding on the main thread. - * * @private */ - private static transcodeSync(arrayBuffer: ArrayBuffer): TranscodedResourcesArray + public static transcodeSync(arrayBuffer: ArrayBuffer): TranscodedResourcesArray { - const BASIS = BasisLoader.basisBinding; + if (!BasisParser.defaultRGBAFormat && !BasisParser.defaultRGBFormat) + { + BasisParser.autoDetectFormats(); + } + + const BASIS = BasisParser.basisBinding; const data = new Uint8Array(arrayBuffer); const basisFile = new BASIS.BasisFile(data); @@ -295,12 +181,12 @@ export class BasisLoader const hasAlpha = basisFile.getHasAlpha(); const basisFormat = hasAlpha - ? BasisLoader.defaultRGBAFormat.basisFormat - : BasisLoader.defaultRGBFormat.basisFormat; + ? BasisParser.defaultRGBAFormat.basisFormat + : BasisParser.defaultRGBFormat.basisFormat; const basisFallbackFormat = BASIS_FORMATS.cTFRGB565; const imageResources = new Array(imageCount); - let fallbackMode = BasisLoader.fallbackMode; + let fallbackMode = BasisParser.fallbackMode; if (!basisFile.startTranscoding()) { @@ -375,7 +261,7 @@ export class BasisLoader width: alignedWidth, height: alignedHeight, levelBuffers: imageLevels, - levels + levels, }); } else @@ -400,7 +286,6 @@ export class BasisLoader /** * Detects the available compressed texture formats on the device. - * * @param extensions - extensions provided by a WebGL context * @ignore */ @@ -409,7 +294,7 @@ export class BasisLoader // Auto-detect WebGL compressed-texture extensions if (!extensions) { - const canvas = document.createElement('canvas'); + const canvas = settings.ADAPTER.createCanvas(); const gl = canvas.getContext('webgl'); if (!gl) @@ -427,7 +312,7 @@ export class BasisLoader pvrtc: gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc'), atc: gl.getExtension('WEBGL_compressed_texture_atc'), - astc: gl.getExtension('WEBGL_compressed_texture_astc') + astc: gl.getExtension('WEBGL_compressed_texture_astc'), }; } @@ -470,19 +355,19 @@ export class BasisLoader if (internalFormat) { - BasisLoader[detectWithAlpha ? 'defaultRGBAFormat' : 'defaultRGBFormat'] = { + BasisParser[detectWithAlpha ? 'defaultRGBAFormat' : 'defaultRGBFormat'] = { textureFormat: internalFormat, basisFormat, }; } else { - BasisLoader[detectWithAlpha ? 'defaultRGBAFormat' : 'defaultRGBFormat'] = { + BasisParser[detectWithAlpha ? 'defaultRGBAFormat' : 'defaultRGBFormat'] = { textureFormat: TYPES.UNSIGNED_SHORT_5_6_5, - basisFormat: BASIS_FORMATS.cTFRGB565 + basisFormat: BASIS_FORMATS.cTFRGB565, }; - BasisLoader.fallbackMode = true; + BasisParser.fallbackMode = true; } } } @@ -491,8 +376,7 @@ export class BasisLoader * Binds the basis_universal transcoder to decompress *.basis files. You must initialize the transcoder library yourself. * * ```js - * import { BasisLoader } from '@pixi/basis'; - * import { Loader } from '@pixi/loaders'; + * import { BasisParser } from '@pixi/basis'; * * // window.BASIS() returns a Promise-like object * window.BASIS().then((basisLibrary) => @@ -500,41 +384,38 @@ export class BasisLoader * // Initialize basis-library; otherwise, transcoded results maybe corrupt! * basisLibrary.initializeBasis(); * - * // Bind BasisLoader to the transcoder - * BasisLoader.bindTranscoder(basisLibrary); + * // Bind BasisParser to the transcoder + * BasisParser.bindTranscoder(basisLibrary); * }); * ``` - * * @param basisLibrary - the initialized transcoder library * @private */ static bindTranscoder(basisLibrary: BasisBinding): void { - BasisLoader.basisBinding = basisLibrary; + BasisParser.basisBinding = basisLibrary; } /** - * Loads the transcoder source code for use in {@link PIXI.BasisLoader.TranscoderWorker}. - * + * Loads the transcoder source code for use in {@link PIXI.BasisParser.TranscoderWorker}. * @private * @param jsURL - URL to the javascript basis transcoder * @param wasmURL - URL to the wasm basis transcoder */ static loadTranscoder(jsURL: string, wasmURL: string): Promise<[void, void]> { - return BasisLoader.TranscoderWorker.loadTranscoder(jsURL, wasmURL); + return BasisParser.TranscoderWorker.loadTranscoder(jsURL, wasmURL); } /** * Set the transcoder source code directly - * * @private * @param jsSource - source for the javascript basis transcoder * @param wasmSource - source for the wasm basis transcoder */ static setTranscoder(jsSource: string, wasmSource: ArrayBuffer): void { - BasisLoader.TranscoderWorker.setTranscoder(jsSource, wasmSource); + BasisParser.TranscoderWorker.setTranscoder(jsSource, wasmSource); } static TranscoderWorker: typeof TranscoderWorker = TranscoderWorker; @@ -554,6 +435,3 @@ export class BasisLoader } } } - -// Auto-detect compressed texture formats once @pixi/basis is imported! -BasisLoader.autoDetectFormats(); diff --git a/packages/basis/src/loader/detectBasis.ts b/packages/basis/src/loader/detectBasis.ts new file mode 100644 index 00000000000..b93ccc2e963 --- /dev/null +++ b/packages/basis/src/loader/detectBasis.ts @@ -0,0 +1,16 @@ +import { extensions, ExtensionType } from '@pixi/core'; +import type { FormatDetectionParser } from '@pixi/assets'; +import { addFormats, removeFormats } from '@pixi/assets'; +import { BasisParser } from './BasisParser'; + +export const detectBasis = { + extension: { + type: ExtensionType.DetectionParser, + priority: 3, + }, + test: async (): Promise => !!(BasisParser.basisBinding && BasisParser.TranscoderWorker.wasmSource), + add: addFormats('basis'), + remove: removeFormats('basis') +} as FormatDetectionParser; + +extensions.add(detectBasis); diff --git a/packages/basis/src/loader/index.ts b/packages/basis/src/loader/index.ts new file mode 100644 index 00000000000..76f6f3bdfe1 --- /dev/null +++ b/packages/basis/src/loader/index.ts @@ -0,0 +1,3 @@ +export * from './BasisParser'; +export * from './detectBasis'; +export * from './loadBasis'; diff --git a/packages/basis/src/loader/loadBasis.ts b/packages/basis/src/loader/loadBasis.ts new file mode 100644 index 00000000000..8f6f04f4831 --- /dev/null +++ b/packages/basis/src/loader/loadBasis.ts @@ -0,0 +1,69 @@ +import { BaseTexture, extensions, ExtensionType, settings, ALPHA_MODES, FORMATS, MIPMAP_MODES } from '@pixi/core'; +import { checkExtension, createTexture, LoaderParserPriority } from '@pixi/assets'; +import { CompressedTextureResource } from '@pixi/compressed-textures'; +import { BASIS_FORMATS, BASIS_FORMAT_TO_TYPE } from '../Basis'; +import { BasisParser } from './BasisParser'; +import { TranscoderWorker } from '../TranscoderWorker'; + +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; +import type { IBaseTextureOptions, Texture, TYPES } from '@pixi/core'; + +/** Load BASIS textures! */ +export const loadBasis = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.High, + }, + + test(url: string): boolean + { + return checkExtension(url, '.basis'); + }, + + async load(url: string, asset: LoadAsset, loader: Loader): Promise + { + await TranscoderWorker.onTranscoderInitialized; + + // get an array buffer... + const response = await settings.ADAPTER.fetch(url); + + const arrayBuffer = await response.arrayBuffer(); + + const resources = await BasisParser.transcode(arrayBuffer); + + const type: TYPES = BASIS_FORMAT_TO_TYPE[resources.basisFormat]; + const format: FORMATS = resources.basisFormat !== BASIS_FORMATS.cTFRGBA32 ? FORMATS.RGB : FORMATS.RGBA; + + const textures = resources.map((resource) => + { + const base = new BaseTexture(resource, { + mipmap: resource instanceof CompressedTextureResource && resource.levels > 1 + ? MIPMAP_MODES.ON_MANUAL + : MIPMAP_MODES.OFF, + alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, + type, + format, + ...asset.data, + }); + + return createTexture(base, loader, url); + }); + + return textures.length === 1 ? textures[0] : textures; + }, + + unload(texture): void + { + if (Array.isArray(texture)) + { + texture.forEach((t) => t.destroy(true)); + } + else + { + texture.destroy(true); + } + } + +} as LoaderParser; + +extensions.add(loadBasis); diff --git a/packages/basis/test/basis.tests.ts b/packages/basis/test/basis.tests.ts new file mode 100644 index 00000000000..1a1e0e52ee9 --- /dev/null +++ b/packages/basis/test/basis.tests.ts @@ -0,0 +1,22 @@ +describe('Basis loading', () => +{ + // CRASHES JEST - ELECTRON + it.skip('should load a a Basis image', async () => + { + // await BasisLoader.loadTranscoder( + // 'https://cdn.jsdelivr.net/npm/@pixi/basis@6.3.2/assets/basis_transcoder.js', + // 'https://cdn.jsdelivr.net/npm/@pixi/basis@6.3.2/assets/basis_transcoder.wasm' + // ); + + // // console.log('DOING!!'); + // const loader = new Loader(); + + // loader['_parsers'].push(loadBasis); + + // const texture: Texture = await loader.load(`https://pixijs.io/compressed-textures-example/images/kodim20.basis`); + + // expect(texture.baseTexture.valid).toBe(true); + // expect(texture.width).toBe(1000); + // expect(texture.height).toBe(664); + }); +}); diff --git a/packages/loaders/LICENSE b/packages/canvas-display/LICENSE similarity index 100% rename from packages/loaders/LICENSE rename to packages/canvas-display/LICENSE diff --git a/packages/canvas/canvas-display/README.md b/packages/canvas-display/README.md similarity index 100% rename from packages/canvas/canvas-display/README.md rename to packages/canvas-display/README.md diff --git a/packages/canvas-display/global.d.ts b/packages/canvas-display/global.d.ts new file mode 100644 index 00000000000..f6f6ffd6086 --- /dev/null +++ b/packages/canvas-display/global.d.ts @@ -0,0 +1,12 @@ +declare namespace GlobalMixins +{ + interface DisplayObject + { + renderCanvas?(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; + } + + interface Container + { + _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; + } +} diff --git a/packages/canvas/canvas-display/package.json b/packages/canvas-display/package.json similarity index 56% rename from packages/canvas/canvas-display/package.json rename to packages/canvas-display/package.json index 07f3f428ced..e8e1878c77a 100644 --- a/packages/canvas/canvas-display/package.json +++ b/packages/canvas-display/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/canvas-display", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-display.js", - "module": "dist/esm/canvas-display.js", - "bundle": "dist/browser/canvas-display.js", - "bundleNoExports": true, + "module": "dist/esm/canvas-display.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-display.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-display.js" + } + } + }, "description": "Canvas mixin for the display package", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/display": "6.3.0" - } + "pixiRequirements": [ + "@pixi/display" + ] } diff --git a/packages/canvas/canvas-display/src/Container.ts b/packages/canvas-display/src/Container.ts similarity index 86% rename from packages/canvas/canvas-display/src/Container.ts rename to packages/canvas-display/src/Container.ts index 361298855d2..e2c4954831e 100644 --- a/packages/canvas/canvas-display/src/Container.ts +++ b/packages/canvas-display/src/Container.ts @@ -7,7 +7,7 @@ import type { MaskData } from '@pixi/core'; * @method _renderCanvas * @memberof PIXI.Container# * @protected - * @param {PIXI.CanvasRenderer} renderer - The renderer + * @param {PIXI.CanvasRenderer} _renderer - The renderer */ Container.prototype._renderCanvas = function _renderCanvas(_renderer: CanvasRenderer): void { @@ -30,7 +30,7 @@ Container.prototype.renderCanvas = function renderCanvas(renderer: CanvasRendere if (this._mask) { - renderer.maskManager.pushMask(this._mask as MaskData); + renderer.mask.pushMask(this._mask as MaskData); } this._renderCanvas(renderer); @@ -41,6 +41,6 @@ Container.prototype.renderCanvas = function renderCanvas(renderer: CanvasRendere if (this._mask) { - renderer.maskManager.popMask(renderer); + renderer.mask.popMask(renderer); } }; diff --git a/packages/canvas/canvas-display/src/DisplayObject.ts b/packages/canvas-display/src/DisplayObject.ts similarity index 85% rename from packages/canvas/canvas-display/src/DisplayObject.ts rename to packages/canvas-display/src/DisplayObject.ts index e4d3f4f5310..0e1fca35ff9 100644 --- a/packages/canvas/canvas-display/src/DisplayObject.ts +++ b/packages/canvas-display/src/DisplayObject.ts @@ -5,7 +5,7 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; * Renders the object using the Canvas renderer * @method renderCanvas * @memberof PIXI.Container# - * @param {PIXI.CanvasRenderer} renderer - The renderer + * @param {PIXI.CanvasRenderer} _renderer - The renderer */ DisplayObject.prototype.renderCanvas = function renderCanvas(_renderer: CanvasRenderer): void { diff --git a/packages/canvas/canvas-display/src/index.ts b/packages/canvas-display/src/index.ts similarity index 100% rename from packages/canvas/canvas-display/src/index.ts rename to packages/canvas-display/src/index.ts diff --git a/packages/canvas/canvas-sprite/test/.eslintrc.json b/packages/canvas-display/test/.eslintrc.json similarity index 100% rename from packages/canvas/canvas-sprite/test/.eslintrc.json rename to packages/canvas-display/test/.eslintrc.json diff --git a/packages/canvas-display/test/Container.tests.ts b/packages/canvas-display/test/Container.tests.ts new file mode 100644 index 00000000000..bfe30c8b7d0 --- /dev/null +++ b/packages/canvas-display/test/Container.tests.ts @@ -0,0 +1,53 @@ +import { Container } from '@pixi/display'; +import '@pixi/canvas-display'; + +describe('Container', () => +{ + describe('render', () => + { + it('should not render when object not visible', () => + { + const container = new Container(); + const canvasSpy = jest.spyOn(container, '_renderCanvas'); + + container.visible = false; + + container.renderCanvas(undefined); + expect(canvasSpy).not.toBeCalled(); + }); + + it('should not render when alpha is zero', () => + { + const container = new Container(); + const canvasSpy = jest.spyOn(container, '_renderCanvas'); + + container.worldAlpha = 0; + + container.renderCanvas(undefined); + expect(canvasSpy).not.toBeCalled(); + }); + + it('should not render when object not renderable', () => + { + const container = new Container(); + const canvasSpy = jest.spyOn(container, '_renderCanvas'); + + container.renderable = false; + + container.renderCanvas(undefined); + expect(canvasSpy).not.toBeCalled(); + }); + + it('should render children', () => + { + const container = new Container(); + const child = new Container(); + const canvasSpy = jest.spyOn(child, '_renderCanvas'); + + container.addChild(child); + + container.renderCanvas(undefined); + expect(canvasSpy).toBeCalled(); + }); + }); +}); diff --git a/packages/interaction/LICENSE b/packages/canvas-extract/LICENSE similarity index 100% rename from packages/interaction/LICENSE rename to packages/canvas-extract/LICENSE diff --git a/packages/canvas-extract/README.md b/packages/canvas-extract/README.md new file mode 100644 index 00000000000..e2a27110c52 --- /dev/null +++ b/packages/canvas-extract/README.md @@ -0,0 +1,13 @@ +# @pixi/canvas-extract + +## Installation + +```bash +npm install @pixi/canvas-extract +``` + +## Usage + +```js +import '@pixi/canvas-extract'; +``` \ No newline at end of file diff --git a/packages/canvas-extract/global.d.ts b/packages/canvas-extract/global.d.ts new file mode 100644 index 00000000000..3925c1bc2a8 --- /dev/null +++ b/packages/canvas-extract/global.d.ts @@ -0,0 +1,7 @@ +declare namespace GlobalMixins +{ + interface CanvasRenderer + { + readonly extract: import('@pixi/canvas-extract').CanvasExtract; + } +} diff --git a/packages/canvas/canvas-extract/package.json b/packages/canvas-extract/package.json similarity index 53% rename from packages/canvas/canvas-extract/package.json rename to packages/canvas-extract/package.json index 09ff9b473e2..da3ccd6beff 100644 --- a/packages/canvas/canvas-extract/package.json +++ b/packages/canvas-extract/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-extract", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-extract.js", - "module": "dist/esm/canvas-extract.js", - "bundle": "dist/browser/canvas-extract.js", + "module": "dist/esm/canvas-extract.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-extract.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-extract.js" + } + } + }, "description": "Canvas mixin for the extract package", "author": "Mat Groves", "contributors": [ @@ -20,15 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-renderer", + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/canvas/canvas-extract/src/CanvasExtract.ts b/packages/canvas-extract/src/CanvasExtract.ts similarity index 61% rename from packages/canvas/canvas-extract/src/CanvasExtract.ts rename to packages/canvas-extract/src/CanvasExtract.ts index 1fb0d43ecbf..2c39a22e34e 100644 --- a/packages/canvas/canvas-extract/src/CanvasExtract.ts +++ b/packages/canvas-extract/src/CanvasExtract.ts @@ -1,9 +1,8 @@ -import { RenderTexture } from '@pixi/core'; -import { CanvasRenderTarget } from '@pixi/utils'; -import { Rectangle } from '@pixi/math'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; +import { Rectangle, extensions, ExtensionType, RenderTexture, utils } from '@pixi/core'; + +import type { CanvasRenderer } from '@pixi/canvas-renderer'; import type { DisplayObject } from '@pixi/display'; -import type { BaseRenderTexture } from '@pixi/core'; +import type { BaseRenderTexture, ISystem, ExtensionMetadata } from '@pixi/core'; const TEMP_RECT = new Rectangle(); @@ -11,12 +10,17 @@ const TEMP_RECT = new Rectangle(); * The extract manager provides functionality to export content from the renderers. * * An instance of this class is automatically created by default, and can be found at `renderer.plugins.extract` - * * @class * @memberof PIXI */ -export class CanvasExtract +export class CanvasExtract implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'extract', + type: ExtensionType.CanvasRendererSystem, + }; + /** A reference to the current renderer */ public renderer: CanvasRenderer; @@ -30,14 +34,13 @@ export class CanvasExtract /** * Will return a HTML Image of the target - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer * @param format - Image format, e.g. "image/jpeg" or "image/webp". * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92. - * @return HTML Image of the target + * @returns HTML Image of the target */ - public image(target?: DisplayObject|RenderTexture, format?: string, quality?: number): HTMLImageElement + public image(target?: DisplayObject | RenderTexture, format?: string, quality?: number): HTMLImageElement { const image = new Image(); @@ -49,31 +52,29 @@ export class CanvasExtract /** * Will return a base64 encoded string of this target. It works by calling * `CanvasExtract.getCanvas` and then running toDataURL on that. - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer * @param format - Image format, e.g. "image/jpeg" or "image/webp". * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92. - * @return A base64 encoded string of the texture. + * @returns A base64 encoded string of the texture. */ - public base64(target?: DisplayObject|RenderTexture, format?: string, quality?: number): string + public base64(target?: DisplayObject | RenderTexture, format?: string, quality?: number): string { return this.canvas(target).toDataURL(format, quality); } /** * Creates a Canvas element, renders this target to it and then returns it. - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer - * @return A Canvas element with the texture rendered on. + * @param frame - The frame the extraction is restricted to. + * @returns A Canvas element with the texture rendered on. */ - public canvas(target?: DisplayObject|RenderTexture): HTMLCanvasElement + public canvas(target?: DisplayObject | RenderTexture, frame?: Rectangle): HTMLCanvasElement { const renderer = this.renderer; let context; let resolution; - let frame; let renderTexture; if (target) @@ -92,22 +93,28 @@ export class CanvasExtract { context = (renderTexture.baseTexture as BaseRenderTexture)._canvasRenderTarget.context; resolution = (renderTexture.baseTexture as BaseRenderTexture)._canvasRenderTarget.resolution; - frame = renderTexture.frame; + frame = frame ?? renderTexture.frame; } else { - context = renderer.rootContext; - resolution = renderer.resolution; - frame = TEMP_RECT; - frame.width = this.renderer.width; - frame.height = this.renderer.height; + context = renderer.canvasContext.rootContext; + resolution = renderer._view.resolution; + + if (!frame) + { + frame = TEMP_RECT; + frame.width = renderer.width; + frame.height = renderer.height; + } } - const width = Math.floor((frame.width * resolution) + 1e-4); - const height = Math.floor((frame.height * resolution) + 1e-4); + const x = Math.round(frame.x * resolution); + const y = Math.round(frame.y * resolution); + const width = Math.round(frame.width * resolution); + const height = Math.round(frame.height * resolution); - const canvasBuffer = new CanvasRenderTarget(width, height, 1); - const canvasData = context.getImageData(frame.x * resolution, frame.y * resolution, width, height); + const canvasBuffer = new utils.CanvasRenderTarget(width, height, 1); + const canvasData = context.getImageData(x, y, width, height); canvasBuffer.context.putImageData(canvasData, 0, 0); @@ -118,17 +125,16 @@ export class CanvasExtract /** * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA * order, with integer values between 0 and 255 (included). - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer - * @return One-dimensional array containing the pixel data of the entire texture + * @param frame - The frame the extraction is restricted to. + * @returns One-dimensional array containing the pixel data of the entire texture */ - public pixels(target?: DisplayObject|RenderTexture): Uint8ClampedArray + public pixels(target?: DisplayObject | RenderTexture, frame?: Rectangle): Uint8ClampedArray { const renderer = this.renderer; let context; let resolution; - let frame; let renderTexture; if (target) @@ -147,21 +153,25 @@ export class CanvasExtract { context = (renderTexture.baseTexture as BaseRenderTexture)._canvasRenderTarget.context; resolution = (renderTexture.baseTexture as BaseRenderTexture)._canvasRenderTarget.resolution; - frame = renderTexture.frame; + frame = frame ?? renderTexture.frame; } else { - context = renderer.rootContext; + context = renderer.canvasContext.rootContext; resolution = renderer.resolution; - frame = TEMP_RECT; - frame.width = renderer.width; - frame.height = renderer.height; + + if (!frame) + { + frame = TEMP_RECT; + frame.width = renderer.width; + frame.height = renderer.height; + } } - const x = frame.x * resolution; - const y = frame.y * resolution; - const width = frame.width * resolution; - const height = frame.height * resolution; + const x = Math.round(frame.x * resolution); + const y = Math.round(frame.y * resolution); + const width = Math.round(frame.width * resolution); + const height = Math.round(frame.height * resolution); return context.getImageData(x, y, width, height).data; } @@ -172,3 +182,5 @@ export class CanvasExtract this.renderer = null; } } + +extensions.add(CanvasExtract); diff --git a/packages/canvas/canvas-extract/src/index.ts b/packages/canvas-extract/src/index.ts similarity index 100% rename from packages/canvas/canvas-extract/src/index.ts rename to packages/canvas-extract/src/index.ts diff --git a/packages/canvas-extract/test/CanvasExtract.tests.ts b/packages/canvas-extract/test/CanvasExtract.tests.ts new file mode 100644 index 00000000000..0fb86daf34d --- /dev/null +++ b/packages/canvas-extract/test/CanvasExtract.tests.ts @@ -0,0 +1,67 @@ +import { CanvasExtract } from '@pixi/canvas-extract'; +import { CanvasRenderer } from '@pixi/canvas-renderer'; +import { Sprite } from '@pixi/sprite'; +import { Texture, RenderTexture, utils } from '@pixi/core'; + +import '@pixi/canvas-display'; + +utils.skipHello(); + +describe('CanvasExtract', () => +{ + it('should access extract on renderer', () => + { + const renderer = new CanvasRenderer(); + + expect(renderer.extract).toBeInstanceOf(CanvasExtract); + + renderer.destroy(); + }); + + it('should extract an sprite', () => + { + const renderer = new CanvasRenderer(); + const sprite = new Sprite(Texture.WHITE); + const extract = renderer.extract as CanvasExtract; + + expect(extract.canvas(sprite)).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64(sprite)).toBeString(); + expect(extract.pixels(sprite)).toBeInstanceOf(Uint8ClampedArray); + expect(extract.image(sprite)).toBeInstanceOf(HTMLImageElement); + + renderer.destroy(); + sprite.destroy(); + }); + + it('should extract with no arguments', () => + { + const renderer = new CanvasRenderer(); + const extract = renderer.extract as CanvasExtract; + + expect(extract.canvas()).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64()).toBeString(); + expect(extract.pixels()).toBeInstanceOf(Uint8ClampedArray); + expect(extract.image()).toBeInstanceOf(HTMLImageElement); + + renderer.destroy(); + }); + + it('should extract a render texture', () => + { + const renderer = new CanvasRenderer(); + const extract = renderer.extract as CanvasExtract; + const renderTexture = RenderTexture.create({ width: 10, height: 10 }); + const sprite = new Sprite(Texture.WHITE); + + renderer.render(sprite, { renderTexture }); + + expect(extract.canvas(renderTexture)).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64(renderTexture)).toBeString(); + expect(extract.pixels(renderTexture)).toBeInstanceOf(Uint8ClampedArray); + expect(extract.image(renderTexture)).toBeInstanceOf(HTMLImageElement); + + renderer.destroy(); + renderTexture.destroy(); + sprite.destroy(); + }); +}); diff --git a/packages/filters/filter-noise/LICENSE b/packages/canvas-graphics/LICENSE similarity index 100% rename from packages/filters/filter-noise/LICENSE rename to packages/canvas-graphics/LICENSE diff --git a/packages/canvas-graphics/README.md b/packages/canvas-graphics/README.md new file mode 100644 index 00000000000..c76ff2e60b1 --- /dev/null +++ b/packages/canvas-graphics/README.md @@ -0,0 +1,13 @@ +# @pixi/canvas-graphics + +## Installation + +```bash +npm install @pixi/canvas-graphics +``` + +## Usage + +```js +import '@pixi/canvas-graphics'; +``` \ No newline at end of file diff --git a/packages/canvas-graphics/global.d.ts b/packages/canvas-graphics/global.d.ts new file mode 100644 index 00000000000..7c04f358087 --- /dev/null +++ b/packages/canvas-graphics/global.d.ts @@ -0,0 +1,9 @@ +declare namespace GlobalMixins +{ + interface Graphics + { + _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; + generateCanvasTexture(scaleMode?: import('@pixi/constants').SCALE_MODES, resolution?: number): Texture; + cachedGraphicsData: import('@pixi/graphics').GraphicsData[]; + } +} diff --git a/packages/canvas/canvas-graphics/package.json b/packages/canvas-graphics/package.json similarity index 51% rename from packages/canvas/canvas-graphics/package.json rename to packages/canvas-graphics/package.json index 900922f4cb6..251c015739f 100644 --- a/packages/canvas/canvas-graphics/package.json +++ b/packages/canvas-graphics/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-graphics", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-graphics.js", - "module": "dist/esm/canvas-graphics.js", - "bundle": "dist/browser/canvas-graphics.js", + "module": "dist/esm/canvas-graphics.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-graphics.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-graphics.js" + } + } + }, "description": "Canvas mixin for the graphics package", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,13 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-display", + "@pixi/canvas-renderer", + "@pixi/core", + "@pixi/graphics" + ] } diff --git a/packages/canvas/canvas-graphics/src/CanvasGraphicsRenderer.ts b/packages/canvas-graphics/src/CanvasGraphicsRenderer.ts similarity index 95% rename from packages/canvas/canvas-graphics/src/CanvasGraphicsRenderer.ts rename to packages/canvas-graphics/src/CanvasGraphicsRenderer.ts index 25f6dfa58cf..3b84db4235f 100644 --- a/packages/canvas/canvas-graphics/src/CanvasGraphicsRenderer.ts +++ b/packages/canvas-graphics/src/CanvasGraphicsRenderer.ts @@ -1,11 +1,11 @@ -import { Texture } from '@pixi/core'; -import { SHAPES, Matrix } from '@pixi/math'; -import { canvasUtils, CrossPlatformCanvasRenderingContext2D } from '@pixi/canvas-renderer'; -import type { CanvasRenderer } from '@pixi/canvas-renderer'; -import type { FillStyle, Graphics, GraphicsData, LineStyle } from '@pixi/graphics'; -import type { Circle, Ellipse, Polygon, Rectangle, RoundedRectangle } from '@pixi/math'; +import { SHAPES, Matrix, extensions, ExtensionType, Texture } from '@pixi/core'; +import { canvasUtils } from '@pixi/canvas-renderer'; import { PolygonUtils } from './utils/PolygonUtils'; +import type { CanvasRenderer, CrossPlatformCanvasRenderingContext2D } from '@pixi/canvas-renderer'; +import type { FillStyle, Graphics, GraphicsData, LineStyle } from '@pixi/graphics'; +import type { ExtensionMetadata, Circle, Ellipse, Polygon, Rectangle, RoundedRectangle } from '@pixi/core'; + /* * @author Mat Groves * @@ -20,16 +20,21 @@ import { PolygonUtils } from './utils/PolygonUtils'; /** * Renderer dedicated to drawing and batching graphics objects. - * * @class * @protected * @memberof PIXI */ export class CanvasGraphicsRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'graphics', + type: ExtensionType.CanvasRendererPlugin, + }; + /** A reference to the current renderer */ public renderer: CanvasRenderer; - private _svgMatrix: DOMMatrix|boolean = null; + private _svgMatrix: DOMMatrix | boolean = null; private _tempMatrix: Matrix = new Matrix(); /** @@ -42,13 +47,12 @@ export class CanvasGraphicsRenderer /** * calculates fill/stroke style for canvas - * * @private * @param style - A graphics {@link PIXI.FILL_STYLE} where if `texture` is specified then a tinted CanvasPattern * will be used for the fill.stroke * @param tint - color to set the fill/stroke too. */ - private _calcCanvasStyle(style: FillStyle, tint: number): string|CanvasPattern + private _calcCanvasStyle(style: FillStyle, tint: number): string | CanvasPattern { let res; @@ -74,18 +78,18 @@ export class CanvasGraphicsRenderer /** * Renders a Graphics object to a canvas. - * * @param graphics - the actual graphics object to render */ public render(graphics: Graphics): void { const renderer = this.renderer; - const context = renderer.context; + + const context = renderer.canvasContext.activeContext; const worldAlpha = graphics.worldAlpha; const transform = graphics.transform.worldTransform; - renderer.setContextTransform(transform); - renderer.setBlendMode(graphics.blendMode); + renderer.canvasContext.setContextTransform(transform); + renderer.canvasContext.setBlendMode(graphics.blendMode); const graphicsData = graphics.geometry.graphicsData; @@ -108,7 +112,7 @@ export class CanvasGraphicsRenderer if (data.matrix) { - renderer.setContextTransform(transform.copyTo(this._tempMatrix).append(data.matrix)); + renderer.canvasContext.setContextTransform(transform.copyTo(this._tempMatrix).append(data.matrix)); } if (fillStyle.visible) @@ -390,7 +394,6 @@ export class CanvasGraphicsRenderer /** * Paint stroke for polygon and holes - * * @private * @param shape - Shape to be drawn * @param lineStyle - Line style for the shape @@ -401,7 +404,7 @@ export class CanvasGraphicsRenderer * @param context - The canvas context */ private paintPolygonStroke( - shape: Polygon, lineStyle: LineStyle, contextStrokeStyle: string|CanvasPattern, + shape: Polygon, lineStyle: LineStyle, contextStrokeStyle: string | CanvasPattern, holes: GraphicsData[], holesDirection: boolean[], worldAlpha: number, context: CrossPlatformCanvasRenderingContext2D ): void @@ -463,7 +466,6 @@ export class CanvasGraphicsRenderer /** * Paint Ellipse - * * @private * @param shape - Shape to be drawn * @param fillStyle - Fill for the shape @@ -474,7 +476,7 @@ export class CanvasGraphicsRenderer */ private paintEllipse( shape: Ellipse, fillStyle: FillStyle, lineStyle: LineStyle, - contextFillStyle: string|CanvasPattern, worldAlpha: number, + contextFillStyle: string | CanvasPattern, worldAlpha: number, context: CrossPlatformCanvasRenderingContext2D): void { // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas @@ -525,7 +527,6 @@ export class CanvasGraphicsRenderer /** * Paint Rounded Rectangle - * * @private * @param shape - Shape to be drawn * @param fillStyle - Fill for the shape @@ -536,7 +537,7 @@ export class CanvasGraphicsRenderer */ private paintRoundedRectangle( shape: RoundedRectangle, fillStyle: FillStyle, lineStyle: LineStyle, - contextFillStyle: string|CanvasPattern, worldAlpha: number, + contextFillStyle: string | CanvasPattern, worldAlpha: number, context: CrossPlatformCanvasRenderingContext2D ): void { @@ -595,7 +596,7 @@ export class CanvasGraphicsRenderer { const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); - if (svg && svg.createSVGMatrix) + if (svg?.createSVGMatrix) { this._svgMatrix = svg.createSVGMatrix(); } @@ -624,3 +625,5 @@ export class CanvasGraphicsRenderer this._tempMatrix = null; } } + +extensions.add(CanvasGraphicsRenderer); diff --git a/packages/canvas/canvas-graphics/src/Graphics.ts b/packages/canvas-graphics/src/Graphics.ts similarity index 82% rename from packages/canvas/canvas-graphics/src/Graphics.ts rename to packages/canvas-graphics/src/Graphics.ts index 3282bda3080..0564e5de25c 100644 --- a/packages/canvas/canvas-graphics/src/Graphics.ts +++ b/packages/canvas-graphics/src/Graphics.ts @@ -1,10 +1,8 @@ import { Graphics } from '@pixi/graphics'; import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { RenderTexture, Texture } from '@pixi/core'; -import { Matrix } from '@pixi/math'; +import { Matrix, RenderTexture, Texture } from '@pixi/core'; -import type { SCALE_MODES } from '@pixi/constants'; -import type { BaseRenderTexture } from '@pixi/core'; +import type { SCALE_MODES, BaseRenderTexture } from '@pixi/core'; let canvasRenderer: CanvasRenderer; const tempMatrix = new Matrix(); @@ -14,11 +12,11 @@ const tempMatrix = new Matrix(); * or the **@pixi/canvas-graphics** package. * @method generateCanvasTexture * @memberof PIXI.Graphics# - * @param {PIXI.SCALE_MODES} scaleMode - The scale mode of the texture. + * @param {PIXI.SCALE_MODES} [scaleMode] - The scale mode of the texture. * @param {number} resolution - The resolution of the texture. - * @return {PIXI.Texture} The new texture. + * @returns {PIXI.Texture} The new texture. */ -Graphics.prototype.generateCanvasTexture = function generateCanvasTexture(scaleMode: SCALE_MODES, resolution = 1): Texture +Graphics.prototype.generateCanvasTexture = function generateCanvasTexture(scaleMode?: SCALE_MODES, resolution = 1): Texture { const bounds = this.getLocalBounds(); @@ -57,7 +55,6 @@ Graphics.prototype.cachedGraphicsData = []; /** * Renders the object using the Canvas renderer - * * @method _renderCanvas * @memberof PIXI.Graphics# * @private diff --git a/packages/canvas/canvas-graphics/src/index.ts b/packages/canvas-graphics/src/index.ts similarity index 100% rename from packages/canvas/canvas-graphics/src/index.ts rename to packages/canvas-graphics/src/index.ts diff --git a/packages/canvas/canvas-graphics/src/utils/PolygonUtils.ts b/packages/canvas-graphics/src/utils/PolygonUtils.ts similarity index 75% rename from packages/canvas/canvas-graphics/src/utils/PolygonUtils.ts rename to packages/canvas-graphics/src/utils/PolygonUtils.ts index ebf17bfc3c8..ffaddc9df44 100644 --- a/packages/canvas/canvas-graphics/src/utils/PolygonUtils.ts +++ b/packages/canvas-graphics/src/utils/PolygonUtils.ts @@ -6,14 +6,13 @@ export class PolygonUtils { /** - * Calculate points of an offset polygon - * @see {@link http://csharphelper.com/blog/2016/01/enlarge-a-polygon-in-c/} - * - * @private - * @param {number[]} points - polygon coordinates - * @param {number} offset - * @return {number[]} - offset points - */ + * Calculate points of an offset polygon + * @see {@link http://csharphelper.com/blog/2016/01/enlarge-a-polygon-in-c/} + * @private + * @param {number[]} points - polygon coordinates + * @param {number} offset + * @returns {number[]} - offset points + */ static offsetPolygon(points: number[], offset: number): number[] { const offsetPoints: number[] = []; @@ -79,20 +78,19 @@ export class PolygonUtils } /** - * Determine the intersection point of two line segments - * @see {@link here http://paulbourke.net/geometry/pointlineplane/} - * - * @private - * @param {number} x1 - x-coordinate of start point at first line - * @param {number} y1 - y-coordinate of start point at first line - * @param {number} x2 - x-coordinate of end point at first line - * @param {number} y2 - y-coordinate of end point at first line - * @param {number} x3 - x-coordinate of start point at second line - * @param {number} y3 - y-coordinate of start point at second line - * @param {number} x4 - x-coordinate of end point at second line - * @param {number} y4 - y-coordinate of end point at second line - * @returns {[number, number] | null} - [x, y] coordinates of intersection - */ + * Determine the intersection point of two line segments + * @see {@link here http://paulbourke.net/geometry/pointlineplane/} + * @private + * @param {number} x1 - x-coordinate of start point at first line + * @param {number} y1 - y-coordinate of start point at first line + * @param {number} x2 - x-coordinate of end point at first line + * @param {number} y2 - y-coordinate of end point at first line + * @param {number} x3 - x-coordinate of start point at second line + * @param {number} y3 - y-coordinate of start point at second line + * @param {number} x4 - x-coordinate of end point at second line + * @param {number} y4 - y-coordinate of end point at second line + * @returns {[number, number] | null} - [x, y] coordinates of intersection + */ static findIntersection( x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number @@ -122,10 +120,9 @@ export class PolygonUtils /** * Determine polygon are clockwise or counterclockwise * @see {@link https://stackoverflow.com/questions/1165647} - * * @private * @param {number[]} polygon - polygon coordinates - * @return {boolean} + * @returns {boolean} - true if polygon is clockwise */ static isPolygonClockwise(polygon: number[]): boolean { diff --git a/packages/canvas/canvas-renderer/test/.eslintrc.json b/packages/canvas-graphics/test/.eslintrc.json similarity index 100% rename from packages/canvas/canvas-renderer/test/.eslintrc.json rename to packages/canvas-graphics/test/.eslintrc.json diff --git a/packages/canvas/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts b/packages/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts similarity index 77% rename from packages/canvas/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts rename to packages/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts index 077119f217a..4c7b75f308b 100644 --- a/packages/canvas/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts +++ b/packages/canvas-graphics/test/CanvasGraphicsRenderer.tests.ts @@ -2,11 +2,11 @@ import { BaseTexture, Texture } from '@pixi/core'; import { Graphics } from '@pixi/graphics'; import { CanvasRenderer } from '@pixi/canvas-renderer'; import { CanvasGraphicsRenderer } from '@pixi/canvas-graphics'; -import { expect } from 'chai'; +import '@pixi/canvas-display'; -describe('CanvasGraphicsRenderer', function () +describe('CanvasGraphicsRenderer', () => { - it('should not create pattern for White Texture', function () + it('should not create pattern for White Texture', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); @@ -14,14 +14,14 @@ describe('CanvasGraphicsRenderer', function () const graphics = new Graphics(); - graphics.beginFill({ texture: Texture.WHITE }); + graphics.beginTextureFill({ texture: Texture.WHITE }); graphics.drawRect(0, 0, 1, 1); graphics.endFill(); try { renderer.render(graphics); - expect(Texture.WHITE.patternCache).to.be.null; + expect(Texture.WHITE.patternCache).toBeNull(); } finally { @@ -29,7 +29,7 @@ describe('CanvasGraphicsRenderer', function () } }); - it('should create pattern for textures', function () + it('should create pattern for textures', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); @@ -50,7 +50,7 @@ describe('CanvasGraphicsRenderer', function () try { renderer.render(graphics); - expect(Object.keys(myTex.patternCache).length).equal(1); + expect(Object.keys(myTex.patternCache).length).toEqual(1); } finally { diff --git a/packages/canvas/canvas-graphics/test/PolygonUtils.tests.ts b/packages/canvas-graphics/test/PolygonUtils.tests.ts similarity index 51% rename from packages/canvas/canvas-graphics/test/PolygonUtils.tests.ts rename to packages/canvas-graphics/test/PolygonUtils.tests.ts index 46740c4288a..f785f55b44e 100644 --- a/packages/canvas/canvas-graphics/test/PolygonUtils.tests.ts +++ b/packages/canvas-graphics/test/PolygonUtils.tests.ts @@ -1,9 +1,8 @@ import { PolygonUtils } from '../src/utils/PolygonUtils'; -import { expect } from 'chai'; -describe('PolygonUtils', function () +describe('PolygonUtils', () => { - it('isPolygonClockwise', function () + it('isPolygonClockwise', () => { const ccwTriangle1 = [0, 0, 1, 0, 0, 1]; const ccwTriangle2 = [1, 0, 0, 1, 0, 0]; @@ -20,19 +19,19 @@ describe('PolygonUtils', function () const cwSquare3 = [1, 0, 0, 0, 0, 1, 1, 1]; const cwSquare4 = [0, 0, 0, 1, 1, 1, 1, 0]; - expect(PolygonUtils.isPolygonClockwise(cwTriangle1)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwTriangle2)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwTriangle3)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwSquare1)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwSquare2)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwSquare3)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(cwSquare4)).to.be.true; - expect(PolygonUtils.isPolygonClockwise(ccwTriangle1)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwTriangle2)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwTriangle3)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwSquare1)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwSquare2)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwSquare3)).to.be.false; - expect(PolygonUtils.isPolygonClockwise(ccwSquare4)).to.be.false; + expect(PolygonUtils.isPolygonClockwise(cwTriangle1)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwTriangle2)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwTriangle3)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwSquare1)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwSquare2)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwSquare3)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(cwSquare4)).toBe(true); + expect(PolygonUtils.isPolygonClockwise(ccwTriangle1)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwTriangle2)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwTriangle3)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwSquare1)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwSquare2)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwSquare3)).toBe(false); + expect(PolygonUtils.isPolygonClockwise(ccwSquare4)).toBe(false); }); }); diff --git a/packages/filters/filter-fxaa/LICENSE b/packages/canvas-mesh/LICENSE similarity index 100% rename from packages/filters/filter-fxaa/LICENSE rename to packages/canvas-mesh/LICENSE diff --git a/packages/canvas-mesh/README.md b/packages/canvas-mesh/README.md new file mode 100644 index 00000000000..1813ddb26b2 --- /dev/null +++ b/packages/canvas-mesh/README.md @@ -0,0 +1,13 @@ +# @pixi/canvas-mesh + +## Installation + +```bash +npm install @pixi/canvas-mesh +``` + +## Usage + +```js +import '@pixi/canvas-mesh'; +``` \ No newline at end of file diff --git a/packages/canvas/canvas-mesh/global.d.ts b/packages/canvas-mesh/global.d.ts similarity index 80% rename from packages/canvas/canvas-mesh/global.d.ts rename to packages/canvas-mesh/global.d.ts index 5974bc236ef..5f84124f938 100644 --- a/packages/canvas/canvas-mesh/global.d.ts +++ b/packages/canvas-mesh/global.d.ts @@ -1,5 +1,7 @@ -declare namespace GlobalMixins { - interface Mesh { +declare namespace GlobalMixins +{ + interface Mesh + { _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; _canvasPadding: number; canvasPadding: number; @@ -8,11 +10,13 @@ declare namespace GlobalMixins { _cachedTexture: import('@pixi/core').Texture; } - interface MeshMaterial { + interface MeshMaterial + { _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer, mesh: import('@pixi/mesh').Mesh): void; } - interface NineSlicePlane { + interface NineSlicePlane + { _cachedTint: number; _tintedCanvas: HTMLCanvasElement; _canvasUvs: number[]; diff --git a/packages/canvas/canvas-mesh/package.json b/packages/canvas-mesh/package.json similarity index 50% rename from packages/canvas/canvas-mesh/package.json rename to packages/canvas-mesh/package.json index 6611e3a4cd1..9bba40a6cec 100644 --- a/packages/canvas/canvas-mesh/package.json +++ b/packages/canvas-mesh/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-mesh", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-mesh.js", - "module": "dist/esm/canvas-mesh.js", - "bundle": "dist/browser/canvas-mesh.js", + "module": "dist/esm/canvas-mesh.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-mesh.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-mesh.js" + } + } + }, "description": "Canvas mixin for the mesh package", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,14 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/settings": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-display", + "@pixi/canvas-renderer", + "@pixi/core", + "@pixi/mesh", + "@pixi/mesh-extras" + ] } diff --git a/packages/canvas/canvas-mesh/src/CanvasMeshRenderer.ts b/packages/canvas-mesh/src/CanvasMeshRenderer.ts similarity index 91% rename from packages/canvas/canvas-mesh/src/CanvasMeshRenderer.ts rename to packages/canvas-mesh/src/CanvasMeshRenderer.ts index b636f0c207e..ec41653bc30 100644 --- a/packages/canvas/canvas-mesh/src/CanvasMeshRenderer.ts +++ b/packages/canvas-mesh/src/CanvasMeshRenderer.ts @@ -1,19 +1,24 @@ -import { Texture } from '@pixi/core'; -import { DRAW_MODES } from '@pixi/constants'; +import { DRAW_MODES, extensions, ExtensionType, Texture } from '@pixi/core'; import { canvasUtils } from '@pixi/canvas-renderer'; +import type { ExtensionMetadata } from '@pixi/core'; import type { CanvasRenderer } from '@pixi/canvas-renderer'; import type { Mesh } from '@pixi/mesh'; /** * Renderer dedicated to meshes. - * * @class * @protected * @memberof PIXI */ export class CanvasMeshRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'mesh', + type: ExtensionType.CanvasRendererPlugin, + }; + /** A reference to the current renderer */ public renderer: CanvasRenderer; @@ -25,7 +30,6 @@ export class CanvasMeshRenderer /** * Renders the Mesh - * * @param mesh - the Mesh to render */ public render(mesh: Mesh): void @@ -33,9 +37,9 @@ export class CanvasMeshRenderer const renderer = this.renderer; const transform = mesh.worldTransform; - renderer.context.globalAlpha = mesh.worldAlpha; - renderer.setBlendMode(mesh.blendMode); - renderer.setContextTransform(transform, mesh.roundPixels); + renderer.canvasContext.activeContext.globalAlpha = mesh.worldAlpha; + renderer.canvasContext.setBlendMode(mesh.blendMode); + renderer.canvasContext.setContextTransform(transform, mesh.roundPixels); if (mesh.drawMode !== DRAW_MODES.TRIANGLES) { @@ -49,7 +53,6 @@ export class CanvasMeshRenderer /** * Draws the object in Triangle Mesh mode - * * @private * @param mesh - the Mesh to render */ @@ -69,7 +72,6 @@ export class CanvasMeshRenderer /** * Draws the object in triangle mode using canvas - * * @private * @param mesh - the current mesh */ @@ -92,7 +94,6 @@ export class CanvasMeshRenderer /** * Draws one of the triangles that from the Mesh - * * @private * @param mesh - the current mesh * @param index0 - the index of the first vertex @@ -101,7 +102,7 @@ export class CanvasMeshRenderer */ private _renderDrawTriangle(mesh: Mesh, index0: number, index1: number, index2: number): void { - const context = this.renderer.context; + const context = this.renderer.canvasContext.activeContext; const vertices = mesh.geometry.buffers[0].data; const { uvs, texture } = mesh; @@ -143,7 +144,7 @@ export class CanvasMeshRenderer let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - const screenPadding = mesh.canvasPadding / this.renderer.resolution; + const screenPadding = mesh.canvasPadding / this.renderer.canvasContext.activeResolution; if (screenPadding > 0) { @@ -233,18 +234,17 @@ export class CanvasMeshRenderer ); context.restore(); - this.renderer.invalidateBlendMode(); + this.renderer.canvasContext.invalidateBlendMode(); } /** * Renders a flat Mesh - * * @private * @param mesh - The Mesh to render */ renderMeshFlat(mesh: Mesh): void { - const context = this.renderer.context; + const context = this.renderer.canvasContext.activeContext; const vertices = mesh.geometry.getBuffer('aVertexPosition').data; const length = vertices.length / 2; @@ -282,3 +282,5 @@ export class CanvasMeshRenderer this.renderer = null; } } + +extensions.add(CanvasMeshRenderer); diff --git a/packages/canvas/canvas-mesh/src/Mesh.ts b/packages/canvas-mesh/src/Mesh.ts similarity index 99% rename from packages/canvas/canvas-mesh/src/Mesh.ts rename to packages/canvas-mesh/src/Mesh.ts index 04309c1680d..beb0ea571b4 100644 --- a/packages/canvas/canvas-mesh/src/Mesh.ts +++ b/packages/canvas-mesh/src/Mesh.ts @@ -31,7 +31,6 @@ Mesh.prototype._cachedTexture = null; /** * Renders the object using the Canvas renderer - * * @private * @method _renderCanvas * @memberof PIXI.Mesh# @@ -65,7 +64,6 @@ Mesh.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRenderer): /** * Internal variable for `canvasPadding`. - * * @private * @memberof PIXI.Mesh * @member {number} @@ -76,7 +74,6 @@ Mesh.prototype._canvasPadding = null; /** * Triangles in canvas mode are automatically antialiased, use this value to force triangles * to overlap a bit with each other. To set the global default, set {@link PIXI.settings.MESH_CANVAS_PADDING} - * * @see PIXI.settings.MESH_CANVAS_PADDING * @member {number} canvasPadding * @memberof PIXI.SimpleMesh# diff --git a/packages/canvas/canvas-mesh/src/MeshMaterial.ts b/packages/canvas-mesh/src/MeshMaterial.ts similarity index 99% rename from packages/canvas/canvas-mesh/src/MeshMaterial.ts rename to packages/canvas-mesh/src/MeshMaterial.ts index 73bca4b293d..55d4436d986 100644 --- a/packages/canvas/canvas-mesh/src/MeshMaterial.ts +++ b/packages/canvas-mesh/src/MeshMaterial.ts @@ -5,7 +5,6 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; /** * Renders the mesh using the Canvas renderer - * * @protected * @method render * @memberof PIXI.MeshMaterial# diff --git a/packages/canvas/canvas-mesh/src/NineSlicePlane.ts b/packages/canvas-mesh/src/NineSlicePlane.ts similarity index 93% rename from packages/canvas/canvas-mesh/src/NineSlicePlane.ts rename to packages/canvas-mesh/src/NineSlicePlane.ts index 7997c2b5cbc..8502b0d15ed 100644 --- a/packages/canvas/canvas-mesh/src/NineSlicePlane.ts +++ b/packages/canvas-mesh/src/NineSlicePlane.ts @@ -29,7 +29,6 @@ NineSlicePlane.prototype._canvasUvs = null; /** * Renders the object using the Canvas renderer - * * @private * @method _renderCanvas * @memberof PIXI.NineSlicePlane# @@ -37,7 +36,7 @@ NineSlicePlane.prototype._canvasUvs = null; */ NineSlicePlane.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRenderer): void { - const context = renderer.context; + const context = renderer.canvasContext.activeContext; const transform = this.worldTransform; const isTinted = this.tint !== 0xFFFFFF; const texture = this.texture; @@ -89,8 +88,8 @@ NineSlicePlane.prototype._renderCanvas = function _renderCanvas(renderer: Canvas } context.globalAlpha = this.worldAlpha; - renderer.setBlendMode(this.blendMode); - renderer.setContextTransform(transform, this.roundPixels); + renderer.canvasContext.setBlendMode(this.blendMode); + renderer.canvasContext.setContextTransform(transform, this.roundPixels); for (let row = 0; row < 3; row++) { diff --git a/packages/canvas/canvas-mesh/src/SimpleMesh.ts b/packages/canvas-mesh/src/SimpleMesh.ts similarity index 99% rename from packages/canvas/canvas-mesh/src/SimpleMesh.ts rename to packages/canvas-mesh/src/SimpleMesh.ts index 85d69105718..d343fe6bda9 100644 --- a/packages/canvas/canvas-mesh/src/SimpleMesh.ts +++ b/packages/canvas-mesh/src/SimpleMesh.ts @@ -4,7 +4,6 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; /** * Renders the object using the Canvas renderer - * * @private * @method _renderCanvas * @memberof PIXI.Mesh# diff --git a/packages/canvas/canvas-mesh/src/SimpleRope.ts b/packages/canvas-mesh/src/SimpleRope.ts similarity index 99% rename from packages/canvas/canvas-mesh/src/SimpleRope.ts rename to packages/canvas-mesh/src/SimpleRope.ts index 428de431771..532e8157ada 100644 --- a/packages/canvas/canvas-mesh/src/SimpleRope.ts +++ b/packages/canvas-mesh/src/SimpleRope.ts @@ -5,7 +5,6 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; /** * Renders the object using the Canvas renderer - * * @protected * @method _renderCanvas * @memberof PIXI.Mesh# diff --git a/packages/canvas/canvas-mesh/src/index.ts b/packages/canvas-mesh/src/index.ts similarity index 100% rename from packages/canvas/canvas-mesh/src/index.ts rename to packages/canvas-mesh/src/index.ts diff --git a/packages/canvas/canvas-mesh/src/settings.ts b/packages/canvas-mesh/src/settings.ts similarity index 83% rename from packages/canvas/canvas-mesh/src/settings.ts rename to packages/canvas-mesh/src/settings.ts index 39cd9f52058..5a138018419 100644 --- a/packages/canvas/canvas-mesh/src/settings.ts +++ b/packages/canvas-mesh/src/settings.ts @@ -1,8 +1,7 @@ -import { settings } from '@pixi/settings'; +import { settings } from '@pixi/core'; /** * Default `canvasPadding` for canvas-based Mesh rendering. - * * @see PIXI.Mesh2d#canvasPadding * @static * @memberof PIXI.settings diff --git a/packages/canvas/canvas-mesh/test/.eslintrc.json b/packages/canvas-mesh/test/.eslintrc.json similarity index 100% rename from packages/canvas/canvas-mesh/test/.eslintrc.json rename to packages/canvas-mesh/test/.eslintrc.json diff --git a/packages/canvas/canvas-mesh/test/NineSlicePlane.tests.ts b/packages/canvas-mesh/test/NineSlicePlane.tests.ts similarity index 59% rename from packages/canvas/canvas-mesh/test/NineSlicePlane.tests.ts rename to packages/canvas-mesh/test/NineSlicePlane.tests.ts index 7c82a694b8c..d7fbb6671ac 100644 --- a/packages/canvas/canvas-mesh/test/NineSlicePlane.tests.ts +++ b/packages/canvas-mesh/test/NineSlicePlane.tests.ts @@ -2,22 +2,24 @@ import { Texture, RenderTexture } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; import { CanvasRenderer } from '@pixi/canvas-renderer'; import { NineSlicePlane } from '@pixi/mesh-extras'; -import { expect } from 'chai'; +import '@pixi/canvas-display'; -describe('NineSlicePlane', function () +describe('NineSlicePlane', () => { - before(function () + let renderer: CanvasRenderer; + + beforeAll(() => { - this.renderer = new CanvasRenderer(); + renderer = new CanvasRenderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should be renderable with renderTexture in canvas', function () + it('should be renderable with renderTexture in canvas', () => { const rt = RenderTexture.create({ width: 10, height: 10 }); const spr = new Sprite(Texture.WHITE); @@ -27,6 +29,6 @@ describe('NineSlicePlane', function () const nineSlicePlane = new NineSlicePlane(rt, 1, 1, 1, 1); - expect(() => { renderer.render(nineSlicePlane); }).to.not.throw(); + expect(() => { renderer.render(nineSlicePlane); }).not.toThrowError(); }); }); diff --git a/packages/filters/filter-displacement/LICENSE b/packages/canvas-particle-container/LICENSE similarity index 100% rename from packages/filters/filter-displacement/LICENSE rename to packages/canvas-particle-container/LICENSE diff --git a/packages/canvas/canvas-particle-container/README.md b/packages/canvas-particle-container/README.md similarity index 100% rename from packages/canvas/canvas-particle-container/README.md rename to packages/canvas-particle-container/README.md diff --git a/packages/canvas/canvas-particle-container/package.json b/packages/canvas-particle-container/package.json similarity index 54% rename from packages/canvas/canvas-particle-container/package.json rename to packages/canvas-particle-container/package.json index a90dd5e2486..32f21b28ef3 100644 --- a/packages/canvas/canvas-particle-container/package.json +++ b/packages/canvas-particle-container/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/canvas-particle-container", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-particle-container.js", - "module": "dist/esm/canvas-particle-container.js", - "bundle": "dist/browser/canvas-particle-container.js", - "bundleNoExports": true, + "module": "dist/esm/canvas-particle-container.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-particle-container.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-particle-container.js" + } + } + }, "description": "Canvas mixin for the particles package", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/particle-container": "6.3.0" - } + "pixiRequirements": [ + "@pixi/particle-container" + ] } diff --git a/packages/canvas/canvas-particle-container/src/ParticleContainer.ts b/packages/canvas-particle-container/src/ParticleContainer.ts similarity index 81% rename from packages/canvas/canvas-particle-container/src/ParticleContainer.ts rename to packages/canvas-particle-container/src/ParticleContainer.ts index deb7f9e4180..800d05eaa3a 100644 --- a/packages/canvas/canvas-particle-container/src/ParticleContainer.ts +++ b/packages/canvas-particle-container/src/ParticleContainer.ts @@ -1,5 +1,4 @@ import { ParticleContainer } from '@pixi/particle-container'; -import type { Sprite } from '@pixi/sprite'; import type { CanvasRenderer } from '@pixi/canvas-renderer'; /** @@ -16,7 +15,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva return; } - const context = renderer.context; + const context = renderer.canvasContext.activeContext; const transform = this.worldTransform; let isRotated = true; @@ -26,7 +25,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva let finalWidth = 0; let finalHeight = 0; - renderer.setBlendMode(this.blendMode); + renderer.canvasContext.setBlendMode(this.blendMode); context.globalAlpha = this.worldAlpha; @@ -34,7 +33,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva for (let i = 0; i < this.children.length; ++i) { - const child = this.children[i] as Sprite; + const child = this.children[i]; if (!child.visible) { @@ -55,7 +54,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call if (isRotated) { - renderer.setContextTransform(transform, false, 1); + renderer.canvasContext.setContextTransform(transform, false, 1); isRotated = false; } @@ -76,7 +75,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva const childTransform = child.worldTransform; - renderer.setContextTransform(childTransform, this.roundPixels, 1); + renderer.canvasContext.setContextTransform(childTransform, this.roundPixels, 1); positionX = ((child.anchor.x) * (-frame.width)) + 0.5; positionY = ((child.anchor.y) * (-frame.height)) + 0.5; @@ -86,6 +85,7 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva } const resolution = child._texture.baseTexture.resolution; + const contextResolution = renderer.canvasContext.activeResolution; context.drawImage( child._texture.baseTexture.getDrawableSource(), @@ -93,10 +93,10 @@ ParticleContainer.prototype.renderCanvas = function renderCanvas(renderer: Canva frame.y * resolution, frame.width * resolution, frame.height * resolution, - positionX * renderer.resolution, - positionY * renderer.resolution, - finalWidth * renderer.resolution, - finalHeight * renderer.resolution + positionX * contextResolution, + positionY * contextResolution, + finalWidth * contextResolution, + finalHeight * contextResolution ); } }; diff --git a/packages/canvas/canvas-particle-container/src/index.ts b/packages/canvas-particle-container/src/index.ts similarity index 100% rename from packages/canvas/canvas-particle-container/src/index.ts rename to packages/canvas-particle-container/src/index.ts diff --git a/packages/filters/filter-color-matrix/LICENSE b/packages/canvas-prepare/LICENSE similarity index 100% rename from packages/filters/filter-color-matrix/LICENSE rename to packages/canvas-prepare/LICENSE diff --git a/packages/canvas-prepare/README.md b/packages/canvas-prepare/README.md new file mode 100644 index 00000000000..050c9d3eb88 --- /dev/null +++ b/packages/canvas-prepare/README.md @@ -0,0 +1,13 @@ +# @pixi/canvas-prepare + +## Installation + +```bash +npm install @pixi/canvas-prepare +``` + +## Usage + +```js +import '@pixi/canvas-prepare'; +``` \ No newline at end of file diff --git a/packages/canvas-prepare/global.d.ts b/packages/canvas-prepare/global.d.ts new file mode 100644 index 00000000000..4aaf84a20dc --- /dev/null +++ b/packages/canvas-prepare/global.d.ts @@ -0,0 +1,7 @@ +declare namespace GlobalMixins +{ + interface CanvasRenderer + { + readonly prepare: import('@pixi/canvas-prepare').CanvasPrepare; + } +} diff --git a/packages/canvas/canvas-prepare/package.json b/packages/canvas-prepare/package.json similarity index 53% rename from packages/canvas/canvas-prepare/package.json rename to packages/canvas-prepare/package.json index e19b9a53079..5a3eea8c96a 100644 --- a/packages/canvas/canvas-prepare/package.json +++ b/packages/canvas-prepare/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-prepare", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-prepare.js", - "module": "dist/esm/canvas-prepare.js", - "bundle": "dist/browser/canvas-prepare.js", + "module": "dist/esm/canvas-prepare.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-prepare.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-prepare.js" + } + } + }, "description": "Canvas mixin for the prepare package", "author": "Mat Groves", "contributors": [ @@ -20,13 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/prepare": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-renderer", + "@pixi/core", + "@pixi/prepare" + ] } diff --git a/packages/canvas/canvas-prepare/src/CanvasPrepare.ts b/packages/canvas-prepare/src/CanvasPrepare.ts similarity index 79% rename from packages/canvas/canvas-prepare/src/CanvasPrepare.ts rename to packages/canvas-prepare/src/CanvasPrepare.ts index 1e751c4477e..cb53bb4e964 100644 --- a/packages/canvas/canvas-prepare/src/CanvasPrepare.ts +++ b/packages/canvas-prepare/src/CanvasPrepare.ts @@ -1,7 +1,7 @@ -import { BaseTexture } from '@pixi/core'; +import { settings, BaseTexture, extensions, ExtensionType } from '@pixi/core'; import { BasePrepare } from '@pixi/prepare'; -import type { AbstractRenderer } from '@pixi/core'; +import type { ISystem, ExtensionMetadata, IRenderer } from '@pixi/core'; import type { CanvasRenderer } from '@pixi/canvas-renderer'; import type { IDisplayObjectExtended } from '@pixi/prepare'; @@ -9,13 +9,12 @@ const CANVAS_START_SIZE = 16; /** * Built-in hook to upload PIXI.Texture objects to the GPU. - * * @private * @param prepare - Instance of CanvasPrepare * @param item - Item to check - * @return If item was uploaded. + * @returns If item was uploaded. */ -function uploadBaseTextures(prepare: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended): boolean +function uploadBaseTextures(prepare: IRenderer | BasePrepare, item: IDisplayObjectExtended): boolean { const tempPrepare = prepare as CanvasPrepare; @@ -50,13 +49,18 @@ function uploadBaseTextures(prepare: AbstractRenderer | BasePrepare, item: IDisp * textures to an offline canvas. This draw call will force the texture to be moved onto the GPU. * * An instance of this class is automatically created by default, and can be found at `renderer.plugins.prepare` - * * @class * @extends PIXI.BasePrepare * @memberof PIXI */ -export class CanvasPrepare extends BasePrepare +export class CanvasPrepare extends BasePrepare implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'prepare', + type: ExtensionType.CanvasRendererSystem, + }; + /** * An offline canvas to render textures to * @internal @@ -77,9 +81,10 @@ export class CanvasPrepare extends BasePrepare this.uploadHookHelper = this; - this.canvas = document.createElement('canvas'); - this.canvas.width = CANVAS_START_SIZE; - this.canvas.height = CANVAS_START_SIZE; + this.canvas = settings.ADAPTER.createCanvas( + CANVAS_START_SIZE, + CANVAS_START_SIZE + ); this.ctx = this.canvas.getContext('2d'); @@ -95,3 +100,5 @@ export class CanvasPrepare extends BasePrepare this.canvas = null; } } + +extensions.add(CanvasPrepare); diff --git a/packages/canvas/canvas-prepare/src/index.ts b/packages/canvas-prepare/src/index.ts similarity index 100% rename from packages/canvas/canvas-prepare/src/index.ts rename to packages/canvas-prepare/src/index.ts diff --git a/packages/filters/filter-blur/LICENSE b/packages/canvas-renderer/LICENSE similarity index 100% rename from packages/filters/filter-blur/LICENSE rename to packages/canvas-renderer/LICENSE diff --git a/packages/canvas/canvas-renderer/README.md b/packages/canvas-renderer/README.md similarity index 100% rename from packages/canvas/canvas-renderer/README.md rename to packages/canvas-renderer/README.md diff --git a/packages/canvas/canvas-renderer/global.d.ts b/packages/canvas-renderer/global.d.ts similarity index 88% rename from packages/canvas/canvas-renderer/global.d.ts rename to packages/canvas-renderer/global.d.ts index f81166eb4e1..ca84b3839a1 100644 --- a/packages/canvas/canvas-renderer/global.d.ts +++ b/packages/canvas-renderer/global.d.ts @@ -21,14 +21,20 @@ declare namespace GlobalMixins tintId?: number; } - interface DisplayObject + interface IRendererOptions { - renderCanvas?(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; + forceCanvas?: boolean; } - interface IRendererOptions + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface CanvasRenderer { - forceCanvas?: boolean; + + } + + interface IRenderableObject + { + renderCanvas?(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; } } diff --git a/packages/canvas/canvas-renderer/package.json b/packages/canvas-renderer/package.json similarity index 56% rename from packages/canvas/canvas-renderer/package.json rename to packages/canvas-renderer/package.json index 2bbd1f1dcda..578bcace094 100644 --- a/packages/canvas/canvas-renderer/package.json +++ b/packages/canvas-renderer/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-renderer", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-renderer.js", - "module": "dist/esm/canvas-renderer.js", - "bundle": "dist/browser/canvas-renderer.js", + "module": "dist/esm/canvas-renderer.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-renderer.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-renderer.js" + } + } + }, "description": "Rendering using the Canvas API", "author": "Mat Groves", "contributors": [ @@ -20,15 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/canvas/canvas-renderer/src/BaseTexture.ts b/packages/canvas-renderer/src/BaseTexture.ts similarity index 91% rename from packages/canvas/canvas-renderer/src/BaseTexture.ts rename to packages/canvas-renderer/src/BaseTexture.ts index c8e04c33f37..26b95c02827 100644 --- a/packages/canvas/canvas-renderer/src/BaseTexture.ts +++ b/packages/canvas-renderer/src/BaseTexture.ts @@ -5,7 +5,7 @@ import { BaseTexture, BaseRenderTexture, Texture } from '@pixi/core'; * for rendering with CanvasRenderer. Provided by **@pixi/canvas-renderer** package. * @method getDrawableSource * @memberof PIXI.BaseTexture# - * @return {PIXI.ICanvasImageSource} Source to render with CanvasRenderer + * @returns {PIXI.ICanvasImageSource} Source to render with CanvasRenderer */ BaseTexture.prototype.getDrawableSource = function getDrawableSource(): CanvasImageSource { @@ -16,7 +16,6 @@ BaseTexture.prototype.getDrawableSource = function getDrawableSource(): CanvasIm /** * A reference to the canvas render target (we only need one as this can be shared across renderers) - * * @protected * @member {PIXI.utils.CanvasRenderTarget} _canvasRenderTarget * @memberof PIXI.BaseRenderTexture# diff --git a/packages/canvas-renderer/src/CanvasContextSystem.ts b/packages/canvas-renderer/src/CanvasContextSystem.ts new file mode 100644 index 00000000000..279ff4638f0 --- /dev/null +++ b/packages/canvas-renderer/src/CanvasContextSystem.ts @@ -0,0 +1,228 @@ +import { BLEND_MODES, SCALE_MODES, settings, Matrix, extensions, ExtensionType } from '@pixi/core'; +import { mapCanvasBlendModesToPixi } from './utils/mapCanvasBlendModesToPixi'; + +import type { CanvasRenderer } from './CanvasRenderer'; +import type { ExtensionMetadata, ISystem } from '@pixi/core'; + +const tempMatrix = new Matrix(); + +/** + * Rendering context for all browsers. This includes platform-specific + * properties that are not included in the spec for CanvasRenderingContext2D + * @private + */ +export interface CrossPlatformCanvasRenderingContext2D extends CanvasRenderingContext2D +{ + webkitImageSmoothingEnabled: boolean; + mozImageSmoothingEnabled: boolean; + oImageSmoothingEnabled: boolean; + msImageSmoothingEnabled: boolean; +} + +/* + * Different browsers support different smoothing property names + * this is the list of all platform props. + */ +export type SmoothingEnabledProperties = + 'imageSmoothingEnabled' | + 'webkitImageSmoothingEnabled' | + 'mozImageSmoothingEnabled' | + 'oImageSmoothingEnabled' | + 'msImageSmoothingEnabled'; + +/** + * System that manages the canvas `2d` contexts + * @memberof PIXI + */ +export class CanvasContextSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.CanvasRendererSystem, + name: 'canvasContext', + }; + + /** A reference to the current renderer */ + private renderer: CanvasRenderer; + + /** The root canvas 2d context that everything is drawn with. */ + public rootContext: CrossPlatformCanvasRenderingContext2D; + /** The currently active canvas 2d context (could change with renderTextures) */ + public activeContext: CrossPlatformCanvasRenderingContext2D; + public activeResolution = 1; + + /** The canvas property used to set the canvas smoothing property. */ + public smoothProperty: SmoothingEnabledProperties = 'imageSmoothingEnabled'; + /** Tracks the blend modes useful for this renderer. */ + public readonly blendModes: string[] = mapCanvasBlendModesToPixi(); + + _activeBlendMode: BLEND_MODES = null; + /** Projection transform, passed in render() stored here */ + _projTransform: Matrix = null; + + /** @private */ + _outerBlend = false; + + /** @param renderer - A reference to the current renderer */ + constructor(renderer: CanvasRenderer) + { + this.renderer = renderer; + } + + /** initiates the system */ + init(): void + { + const alpha = this.renderer.background.alpha < 1; + + this.rootContext = this.renderer.view.getContext('2d', { alpha }) as + CrossPlatformCanvasRenderingContext2D; + + this.activeContext = this.rootContext; + + if (!this.rootContext.imageSmoothingEnabled) + { + const rc = this.rootContext; + + if (rc.webkitImageSmoothingEnabled) + { + this.smoothProperty = 'webkitImageSmoothingEnabled'; + } + else if (rc.mozImageSmoothingEnabled) + { + this.smoothProperty = 'mozImageSmoothingEnabled'; + } + else if (rc.oImageSmoothingEnabled) + { + this.smoothProperty = 'oImageSmoothingEnabled'; + } + else if (rc.msImageSmoothingEnabled) + { + this.smoothProperty = 'msImageSmoothingEnabled'; + } + } + } + + /** + * Sets matrix of context. + * called only from render() methods + * takes care about resolution + * @param transform - world matrix of current element + * @param roundPixels - whether to round (tx,ty) coords + * @param localResolution - If specified, used instead of `renderer.resolution` for local scaling + */ + setContextTransform(transform: Matrix, roundPixels?: boolean, localResolution?: number): void + { + let mat = transform; + const proj = this._projTransform; + const contextResolution = this.activeResolution; + + localResolution = localResolution || contextResolution; + + if (proj) + { + mat = tempMatrix; + mat.copyFrom(transform); + mat.prepend(proj); + } + + if (roundPixels) + { + this.activeContext.setTransform( + mat.a * localResolution, + mat.b * localResolution, + mat.c * localResolution, + mat.d * localResolution, + (mat.tx * contextResolution) | 0, + (mat.ty * contextResolution) | 0 + ); + } + else + { + this.activeContext.setTransform( + mat.a * localResolution, + mat.b * localResolution, + mat.c * localResolution, + mat.d * localResolution, + mat.tx * contextResolution, + mat.ty * contextResolution + ); + } + } + + /** + * Clear the canvas of renderer. + * @param {string} [clearColor] - Clear the canvas with this color, except the canvas is transparent. + * @param {number} [alpha] - Alpha to apply to the background fill color. + */ + public clear(clearColor?: string, alpha?: number): void + { + const { activeContext: context, renderer } = this; + + clearColor = clearColor ?? this.renderer.background.colorString; + + context.clearRect(0, 0, renderer.width, renderer.height); + + if (clearColor) + { + context.globalAlpha = alpha ?? this.renderer.background.alpha; + context.fillStyle = clearColor; + context.fillRect(0, 0, renderer.width, renderer.height); + context.globalAlpha = 1; + } + } + + /** + * Sets the blend mode of the renderer. + * @param {number} blendMode - See {@link PIXI.BLEND_MODES} for valid values. + * @param {boolean} [readyForOuterBlend=false] - Some blendModes are dangerous, they affect outer space of sprite. + * Pass `true` only if you are ready to use them. + */ + setBlendMode(blendMode: BLEND_MODES, readyForOuterBlend?: boolean): void + { + const outerBlend = blendMode === BLEND_MODES.SRC_IN + || blendMode === BLEND_MODES.SRC_OUT + || blendMode === BLEND_MODES.DST_IN + || blendMode === BLEND_MODES.DST_ATOP; + + if (!readyForOuterBlend && outerBlend) + { + blendMode = BLEND_MODES.NORMAL; + } + + if (this._activeBlendMode === blendMode) + { + return; + } + + this._activeBlendMode = blendMode; + this._outerBlend = outerBlend; + this.activeContext.globalCompositeOperation = this.blendModes[blendMode]; + } + + resize(): void + { + // reset the scale mode.. oddly this seems to be reset when the canvas is resized. + // surely a browser bug?? Let PixiJS fix that for you.. + if (this.smoothProperty) + { + this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); + } + } + + /** Checks if blend mode has changed. */ + invalidateBlendMode(): void + { + this._activeBlendMode = this.blendModes.indexOf(this.activeContext.globalCompositeOperation); + } + + public destroy(): void + { + this.renderer = null; + this.rootContext = null; + + this.activeContext = null; + this.smoothProperty = null; + } +} + +extensions.add(CanvasContextSystem); diff --git a/packages/canvas/canvas-renderer/src/utils/CanvasMaskManager.ts b/packages/canvas-renderer/src/CanvasMaskSystem.ts similarity index 91% rename from packages/canvas/canvas-renderer/src/utils/CanvasMaskManager.ts rename to packages/canvas-renderer/src/CanvasMaskSystem.ts index 45d1c52812b..46c9b5f77f1 100644 --- a/packages/canvas/canvas-renderer/src/utils/CanvasMaskManager.ts +++ b/packages/canvas-renderer/src/CanvasMaskSystem.ts @@ -1,20 +1,24 @@ -import { Polygon, SHAPES } from '@pixi/math'; +import { SHAPES, extensions, ExtensionType } from '@pixi/core'; -import type { CanvasRenderer } from '../CanvasRenderer'; +import type { ExtensionMetadata, ISystem, MaskData, Polygon } from '@pixi/core'; +import type { CanvasRenderer } from './CanvasRenderer'; import type { Graphics } from '@pixi/graphics'; -import type { MaskData } from '@pixi/core'; import type { Container } from '@pixi/display'; - /** * A set of functions used to handle masking. * * Sprite masking is not supported on the CanvasRenderer. - * * @class * @memberof PIXI */ -export class CanvasMaskManager +export class CanvasMaskSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.CanvasRendererSystem, + name: 'mask', + }; + /** A reference to the current renderer */ private renderer: CanvasRenderer; private _foundShapes: Array = []; @@ -27,7 +31,6 @@ export class CanvasMaskManager /** * This method adds it to the current stack of masks. - * * @param maskData - the maskData that will be pushed */ pushMask(maskData: MaskData | Graphics): void @@ -35,7 +38,7 @@ export class CanvasMaskManager const renderer = this.renderer; const maskObject = ((maskData as MaskData).maskObject || maskData) as Container; - renderer.context.save(); + renderer.canvasContext.activeContext.save(); // TODO support sprite alpha masks?? // lots of effort required. If demand is great enough.. @@ -45,7 +48,7 @@ export class CanvasMaskManager this.recursiveFindShapes(maskObject, foundShapes); if (foundShapes.length > 0) { - const { context } = renderer; + const context = renderer.canvasContext.activeContext; context.beginPath(); @@ -54,7 +57,7 @@ export class CanvasMaskManager const shape = foundShapes[i]; const transform = shape.transform.worldTransform; - this.renderer.setContextTransform(transform); + this.renderer.canvasContext.setContextTransform(transform); this.renderGraphicsShape(shape); } @@ -66,7 +69,6 @@ export class CanvasMaskManager /** * Renders all PIXI.Graphics shapes in a subtree. - * * @param container - container to scan. * @param out - where to put found shapes */ @@ -90,14 +92,13 @@ export class CanvasMaskManager /** * Renders a PIXI.Graphics shape. - * * @param graphics - The object to render. */ renderGraphicsShape(graphics: Graphics): void { graphics.finishPoly(); - const context = this.renderer.context; + const context = this.renderer.canvasContext.activeContext; const graphicsData = graphics.geometry.graphicsData; const len = graphicsData.length; @@ -250,13 +251,12 @@ export class CanvasMaskManager /** * Restores the current drawing context to the state it was before the mask was applied. - * * @param renderer - The renderer context to use. */ popMask(renderer: CanvasRenderer): void { - renderer.context.restore(); - renderer.invalidateBlendMode(); + renderer.canvasContext.activeContext.restore(); + renderer.canvasContext.invalidateBlendMode(); } /** Destroys this canvas mask manager. */ @@ -265,3 +265,5 @@ export class CanvasMaskManager /* empty */ } } + +extensions.add(CanvasMaskSystem); diff --git a/packages/canvas-renderer/src/CanvasObjectRendererSystem.ts b/packages/canvas-renderer/src/CanvasObjectRendererSystem.ts new file mode 100644 index 00000000000..85f98d6d8af --- /dev/null +++ b/packages/canvas-renderer/src/CanvasObjectRendererSystem.ts @@ -0,0 +1,184 @@ +import { + BLEND_MODES, + utils, + extensions, + CanvasResource, + ExtensionType } from '@pixi/core'; + +import type { CanvasRenderer } from './CanvasRenderer'; +import type { + Matrix, + BaseRenderTexture, + ExtensionMetadata, + IRendererRenderOptions, + ISystem, + IRenderableObject, + RenderTexture } from '@pixi/core'; +import type { CrossPlatformCanvasRenderingContext2D } from './CanvasContextSystem'; + +/** + * system that provides a render function that focussing on rendering Pixi Scene Graph objects + * to either the main view or to a renderTexture. Used for Canvas `2d` contexts + * @memberof PIXI + */ +export class CanvasObjectRendererSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.CanvasRendererSystem, + name: 'objectRenderer', + }; + + /** A reference to the current renderer */ + private renderer: CanvasRenderer; + renderingToScreen: boolean; + lastObjectRendered: IRenderableObject; + + /** @param renderer - A reference to the current renderer */ + constructor(renderer: CanvasRenderer) + { + this.renderer = renderer; + } + + /** + * Renders the object to its Canvas view. + * @param displayObject - The object to be rendered. + * @param options - the options to be passed to the renderer + */ + public render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void + { + const renderer = this.renderer; + + if (!renderer.view) + { + return; + } + + const _context = renderer.canvasContext; + + let renderTexture: BaseRenderTexture | RenderTexture; + let clear: boolean; + let transform: Matrix; + let skipUpdateTransform: boolean; + + if (options) + { + renderTexture = options.renderTexture; + clear = options.clear; + transform = options.transform; + skipUpdateTransform = options.skipUpdateTransform; + } + + // can be handy to know! + this.renderingToScreen = !renderTexture; + + renderer.emit('prerender'); + + const rootResolution = renderer.resolution; + + if (renderTexture) + { + renderTexture = renderTexture.castToBaseTexture() as BaseRenderTexture; + + if (!renderTexture._canvasRenderTarget) + { + renderTexture._canvasRenderTarget = new utils.CanvasRenderTarget( + renderTexture.width, + renderTexture.height, + renderTexture.resolution + ); + + renderTexture.resource = new CanvasResource(renderTexture._canvasRenderTarget.canvas); + renderTexture.valid = true; + } + + _context.activeContext = renderTexture._canvasRenderTarget.context as CrossPlatformCanvasRenderingContext2D; + renderer.canvasContext.activeResolution = renderTexture._canvasRenderTarget.resolution; + } + else + { + _context.activeContext = _context.rootContext; + _context.activeResolution = rootResolution; + } + + const context2D = _context.activeContext; + + _context._projTransform = transform || null; + + if (!renderTexture) + { + this.lastObjectRendered = displayObject; + } + + if (!skipUpdateTransform) + { + // update the scene graph + const cacheParent = displayObject.enableTempParent(); + + displayObject.updateTransform(); + displayObject.disableTempParent(cacheParent); + } + + context2D.save(); + context2D.setTransform(1, 0, 0, 1, 0, 0); + context2D.globalAlpha = 1; + _context._activeBlendMode = BLEND_MODES.NORMAL; + _context._outerBlend = false; + context2D.globalCompositeOperation = _context.blendModes[BLEND_MODES.NORMAL]; + + if (clear ?? renderer.background.clearBeforeRender) + { + if (this.renderingToScreen) + { + context2D.clearRect(0, 0, renderer.width, renderer.height); + + const background = renderer.background; + + if (background.alpha > 0) + { + context2D.globalAlpha = background.alpha; + context2D.fillStyle = background.colorString; + context2D.fillRect(0, 0, renderer.width, renderer.height); + context2D.globalAlpha = 1; + } + } + else + { + renderTexture = (renderTexture as BaseRenderTexture); + renderTexture._canvasRenderTarget.clear(); + + const clearColor = renderTexture.clearColor; + + if (clearColor[3] > 0) + { + context2D.globalAlpha = clearColor[3] ?? 1; + context2D.fillStyle = utils.hex2string(utils.rgb2hex(clearColor)); + context2D.fillRect(0, 0, renderTexture.realWidth, renderTexture.realHeight); + context2D.globalAlpha = 1; + } + } + } + + // TODO RENDER TARGET STUFF HERE.. + const tempContext = _context.activeContext; + + _context.activeContext = context2D; + displayObject.renderCanvas(renderer); + _context.activeContext = tempContext; + + context2D.restore(); + + _context.activeResolution = rootResolution; + _context._projTransform = null; + + renderer.emit('postrender'); + } + + public destroy(): void + { + this.lastObjectRendered = null; + this.render = null; + } +} + +extensions.add(CanvasObjectRendererSystem); diff --git a/packages/canvas-renderer/src/CanvasRenderer.ts b/packages/canvas-renderer/src/CanvasRenderer.ts new file mode 100644 index 00000000000..9e52ca81239 --- /dev/null +++ b/packages/canvas-renderer/src/CanvasRenderer.ts @@ -0,0 +1,599 @@ +import { + SystemManager, + extensions, + ExtensionType, + settings, + utils +} from '@pixi/core'; + +import type { CanvasMaskSystem } from './CanvasMaskSystem'; +import type { DisplayObject } from '@pixi/display'; +import type { + BLEND_MODES, + RENDERER_TYPE, + Matrix, + Rectangle, + IRendererOptions, + IRendererPlugins, + IRendererRenderOptions, + RenderTexture, + IRenderableObject, + GenerateTextureSystem, + IRenderer, + BackgroundSystem, + ViewSystem, + PluginSystem, + StartupSystem, + StartupOptions, + ExtensionMetadata, + IGenerateTextureOptions } from '@pixi/core'; +import type { CanvasContextSystem, SmoothingEnabledProperties } from './CanvasContextSystem'; +import type { CanvasObjectRendererSystem } from './CanvasObjectRendererSystem'; + +const { deprecation } = utils; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface CanvasRenderer extends GlobalMixins.CanvasRenderer {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface CanvasRenderer extends GlobalMixins.CanvasRenderer {} + +/** + * The CanvasRenderer draws the scene and all its content onto a 2d canvas. + * + * This renderer should be used for browsers that support WebGL. + * + * This renderer should be used for browsers that do not support WebGL. + * Don't forget to add the view to your DOM or you will not see anything! + * + * Renderer is composed of systems that manage specific tasks. The following systems are added by default + * whenever you create a renderer: + * + * | System | Description | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * + * | Generic Systems | Systems that manage functionality that all renderer types share | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * | {@link PIXI.ViewSystem} | This manages the main view of the renderer usually a Canvas | + * | {@link PIXI.PluginSystem} | This manages plugins for the renderer | + * | {@link PIXI.BackgroundSystem} | This manages the main views background color and alpha | + * | {@link PIXI.StartupSystem} | Boots up a renderer and initiatives all the systems | + * | {@link PIXI.EventSystem} | This manages UI events. | + * | {@link PIXI.GenerateTextureSystem} | This adds the ability to generate textures from any PIXI.DisplayObject | + * + * | PixiJS High-Level Systems | Set of specific systems designed to work with PixiJS objects | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * | {@link PIXI.CanvasContextSystem} | This manages the canvas `2d` contexts and their state | + * | {@link PIXI.CanvasMaskSystem} | This manages masking operations. | + * | {@link PIXI.CanvasRenderSystem} | This adds the ability to render a PIXI.DisplayObject | + * | {@link PIXI.CanvasExtract} | This extracts image data from a PIXI.DisplayObject | + * | {@link PIXI.CanvasPrepare} | This prepares a PIXI.DisplayObject async for rendering | + * + * The breadth of the API surface provided by the renderer is contained within these systems. + * @class + * @memberof PIXI + */ +export class CanvasRenderer extends SystemManager implements IRenderer +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.Renderer, + priority: 0, + }; + + /** + * Used with autoDetectRenderer, this is always supported for any environment, so return true. + * @ignore + */ + static test(): boolean + { + return true; + } + + /** + * Fired after rendering finishes. + * @event PIXI.CanvasRenderer#postrender + */ + /** + * Fired before rendering starts. + * @event PIXI.CanvasRenderer#prerender + */ + + /** + * The type of the renderer. will be PIXI.RENDERER_TYPE.CANVAS + * @member {number} + * @see PIXI.RENDERER_TYPE + */ + public readonly type: RENDERER_TYPE.CANVAS; + + /** When logging Pixi to the console, this is the name we will show */ + public readonly rendererLogId = 'Canvas'; + + // systems.. + /** + * textureGenerator system instance + * @readonly + */ + public textureGenerator: GenerateTextureSystem; + + /** + * background system instance + * @readonly + */ + public background: BackgroundSystem; + + /** + * canvas mask system instance + * @readonly + */ + public mask: CanvasMaskSystem; + + /** + * plugin system instance + * @readonly + */ + public _plugin: PluginSystem; + + /** + * Canvas context system instance + * @readonly + */ + public canvasContext: CanvasContextSystem; + + /** + * Startup system instance + * @readonly + */ + public startup: StartupSystem; + + /** + * View system instance + * @readonly + */ + public _view: ViewSystem; + + /** + * renderer system instance + * @readonly + */ + public objectRenderer: CanvasObjectRendererSystem; + + /** + * @param options - The optional renderer parameters + * @param {number} [options.width=800] - the width of the screen + * @param {number} [options.height=600] - the height of the screen + * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional + * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property. + * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the + * canvas needs to be opaque, possibly for performance reasons on some older devices. + * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for + * resolutions other than 1 + * @param {boolean} [options.antialias=false] - sets antialias + * @param {number} [options.resolution=PIXI.settings.RESOLUTION] - The resolution / device pixel ratio of the renderer. + * @param {boolean} [options.preserveDrawingBuffer=false] - enables drawing buffer preservation, + * enable this if you need to call toDataUrl on the webgl context. + * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or + * not before the new render pass. + * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area + * (shown if not transparent). + * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque). + */ + constructor(options?: IRendererOptions) + { + super(); + + // Add the default render options + options = Object.assign({}, settings.RENDER_OPTIONS, options); + + const systemConfig = { + runners: ['init', 'destroy', 'contextChange', 'reset', 'update', 'postrender', 'prerender', 'resize'], + systems: CanvasRenderer.__systems, + priority: [ + 'textureGenerator', + 'background', + '_view', + '_plugin', + 'startup', + 'mask', + 'canvasContext', + 'objectRenderer' + ], + }; + + this.setup(systemConfig); + + // convert our big blob of options into system specific ones.. + const startupOptions: StartupOptions = { + _plugin: CanvasRenderer.__plugins, + background: { + alpha: options.backgroundAlpha, + color: options.backgroundColor, + clearBeforeRender: options.clearBeforeRender, + }, + _view: { + height: options.height, + width: options.width, + autoDensity: options.autoDensity, + resolution: options.resolution, + } + }; + + this.startup.run(startupOptions); + } + + /** + * Useful function that returns a texture of the display object that can then be used to create sprites + * This can be quite useful if your displayObject is complicated and needs to be reused multiple times. + * @param displayObject - The displayObject the object will be generated from. + * @param {object} options - Generate texture options. + * @param {PIXI.SCALE_MODES} options.scaleMode - The scale mode of the texture. + * @param {number} options.resolution - The resolution / device pixel ratio of the texture being generated. + * @param {PIXI.Rectangle} options.region - The region of the displayObject, that shall be rendered, + * if no region is specified, defaults to the local bounds of the displayObject. + * @param {PIXI.MSAA_QUALITY} options.multisample - The number of samples of the frame buffer. + * @returns A texture of the graphics object. + */ + generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): RenderTexture + { + return this.textureGenerator.generateTexture(displayObject, options); + } + + reset(): void + { + // nothing to be done :D + } + + /** + * Renders the object to its WebGL view. + * @param displayObject - The object to be rendered. + * @param options - Object to use for render options. + * @param {PIXI.RenderTexture} [options.renderTexture] - The render texture to render to. + * @param {boolean} [options.clear=true] - Should the canvas be cleared before the new render. + * @param {PIXI.Matrix} [options.transform] - A transform to apply to the render texture before rendering. + * @param {boolean} [options.skipUpdateTransform=false] - Should we skip the update transform pass? + */ + render(displayObject: DisplayObject, options?: IRendererRenderOptions): void + { + this.objectRenderer.render(displayObject, options); + } + + /** Clear the canvas of renderer. */ + public clear(): void + { + this.canvasContext.clear(); + } + + /** + * Removes everything from the renderer and optionally removes the Canvas DOM element. + * @param {boolean} [removeView=false] - Removes the Canvas element from the DOM. + */ + public destroy(removeView?: boolean): void + { + this.runners.destroy.items.reverse(); + + this.emitWithCustomOptions(this.runners.destroy, { + _view: removeView, + }); + + super.destroy(); + } + + /** Collection of plugins */ + get plugins(): IRendererPlugins + { + return this._plugin.plugins; + } + + /** + * Resizes the canvas view to the specified width and height. + * @param desiredScreenWidth - the desired width of the screen + * @param desiredScreenHeight - the desired height of the screen + */ + public resize(desiredScreenWidth: number, desiredScreenHeight: number): void + { + this._view.resizeView(desiredScreenWidth, desiredScreenHeight); + } + + /** + * Same as view.width, actual number of pixels in the canvas by horizontal. + * @member {number} + * @readonly + * @default 800 + */ + get width(): number + { + return this._view.element.width; + } + + /** + * Same as view.height, actual number of pixels in the canvas by vertical. + * @member {number} + * @readonly + * @default 600 + */ + get height(): number + { + return this._view.element.height; + } + + /** The resolution / device pixel ratio of the renderer. */ + get resolution(): number + { + return this._view.resolution; + } + + /** Whether CSS dimensions of canvas view should be resized to screen dimensions automatically. */ + get autoDensity(): boolean + { + return this._view.autoDensity; + } + + /** The canvas element that everything is drawn to.*/ + get view(): HTMLCanvasElement + { + return this._view.element; + } + + /** + * Measurements of the screen. (0, 0, screenWidth, screenHeight). + * Its safe to use as filterArea or hitArea for the whole stage. + */ + get screen(): Rectangle + { + return this._view.screen; + } + + /** the last object rendered by the renderer. Useful for other plugins like interaction managers */ + get lastObjectRendered(): IRenderableObject + { + return this.objectRenderer.lastObjectRendered; + } + + /** Flag if we are rendering to the screen vs renderTexture */ + get renderingToScreen(): boolean + { + return this.objectRenderer.renderingToScreen; + } + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent PixiJS will use a canvas sized fillRect operation every + * frame to set the canvas background color. If the scene is transparent PixiJS will use clearRect + * to clear the canvas every frame. Disable this by setting this to false. For example, if + * your game has a canvas filling background image you often don't need this set. + */ + get clearBeforeRender(): boolean + { + return this.background.clearBeforeRender; + } + + // deprecated zone.. + + /** + * Tracks the blend modes useful for this renderer. + * @deprecated since 7.0.0 use `renderer.canvasContext.blendModes` instead + */ + get blendModes(): string[] + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.blendModes has been deprecated, please use renderer.canvasContext.blendModes instead'); + // #endif + + return this.canvasContext.blendModes; + } + + /** + * system that manages canvas masks + * @deprecated since 7.0.0 use `renderer.canvasContext.mask` + */ + get maskManager(): CanvasMaskSystem + { + deprecation('7.0.0', 'renderer.maskManager has been deprecated, please use renderer.mask instead'); + + return this.mask; + } + + /** + * Boolean flag controlling canvas refresh. + * @deprecated since 7.0.0 + */ + get refresh(): boolean + { + // #if _DEBUG + deprecation('7.0.0', 'renderer.refresh has been deprecated'); + // #endif + + return true; + } + + /** + * The root canvas 2d context that everything is drawn with. + * @deprecated since 7.0.0 Use `renderer.canvasContext.rootContext instead + */ + get rootContext(): CanvasRenderingContext2D + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.rootContext has been deprecated, please use renderer.canvasContext.rootContext instead'); + // #endif + + return this.canvasContext.rootContext; + } + + /** + * The currently active canvas 2d context (could change with renderTextures) + * @deprecated since 7.0.0 Use `renderer.canvasContext.activeContext instead + */ + get context(): CanvasRenderingContext2D + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.context has been deprecated, please use renderer.canvasContext.activeContext instead'); + // #endif + + return this.canvasContext.activeContext; + } + + /** + * The canvas property used to set the canvas smoothing property. + * @deprecated since 7.0.0 Use `renderer.canvasContext.smoothProperty` instead. + */ + get smoothProperty(): SmoothingEnabledProperties + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.smoothProperty has been deprecated, please use renderer.canvasContext.smoothProperty instead'); + // #endif + + return this.canvasContext.smoothProperty; + } + + /** + * Sets the blend mode of the renderer. + * @param {number} blendMode - See {@link PIXI.BLEND_MODES} for valid values. + * @param {boolean} [readyForOuterBlend=false] - Some blendModes are dangerous, they affect outer space of sprite. + * Pass `true` only if you are ready to use them. + * @deprecated since 7.0.0 Use `renderer.canvasContext.setBlendMode` instead. + */ + setBlendMode(blendMode: BLEND_MODES, readyForOuterBlend?: boolean): void + { + // #if _DEBUG + deprecation('7.0.0', 'renderer.setBlendMode has been deprecated, use renderer.canvasContext.setBlendMode instead'); + // #endif + + this.canvasContext.setBlendMode(blendMode, readyForOuterBlend); + } + + /** + * Checks if blend mode has changed. + * @deprecated since 7.0.0 Use `renderer.canvasContext.invalidateBlendMode` instead. + */ + invalidateBlendMode(): void + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.invalidateBlendMode has been deprecated, use renderer.canvasContext.invalidateBlendMode instead'); + // #endif + + this.canvasContext.invalidateBlendMode(); + } + + /** + * Sets matrix of context. + * called only from render() methods + * takes care about resolution + * @param transform - world matrix of current element + * @param roundPixels - whether to round (tx,ty) coords + * @param localResolution - If specified, used instead of `renderer.resolution` for local scaling + * @deprecated since 7.0.0 - Use `renderer.canvasContext.setContextTransform` instead. + */ + setContextTransform(transform: Matrix, roundPixels?: boolean, localResolution?: number): void + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.setContextTransform has been deprecated, use renderer.canvasContext.setContextTransform instead'); + // #endif + + this.canvasContext.setContextTransform(transform, roundPixels, localResolution); + } + + /** + * The background color to fill if not transparent + * @deprecated since 7.0.0 + */ + get backgroundColor(): number + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundColor has been deprecated, use renderer.background.color instead.'); + // #endif + + return this.background.color; + } + + /** + * @deprecated since 7.0.0 + */ + set backgroundColor(value: number) + { + // #if _DEBUG + deprecation('7.0.0', 'renderer.backgroundColor has been deprecated, use renderer.background.color instead.'); + // #endif + + this.background.color = value; + } + + /** + * The background color alpha. Setting this to 0 will make the canvas transparent. + * @member {number} + * @deprecated since 7.0.0 + */ + get backgroundAlpha(): number + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundAlpha has been deprecated, use renderer.background.alpha instead.'); + // #endif + + return this.background.color; + } + + /** + * @deprecated since 7.0.0 + */ + set backgroundAlpha(value: number) + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundAlpha has been deprecated, use renderer.background.alpha instead.'); + // #endif + + this.background.alpha = value; + } + + /** + * old abstract function not used by canvas renderer + * @deprecated since 7.0.0 + */ + get preserveDrawingBuffer(): boolean + { + // #if _DEBUG + deprecation('7.0.0', 'renderer.preserveDrawingBuffer has been deprecated'); + // #endif + + return false; + } + + /** + * old abstract function not used by canvas renderer + * @deprecated since 7.0.0 + */ + get useContextAlpha(): boolean + { + // #if _DEBUG + deprecation('7.0.0', 'renderer.useContextAlpha has been deprecated'); + // #endif + + return false; + } + + /** @private */ + static readonly __plugins: IRendererPlugins = {}; + + /** @private */ + static readonly __systems: Record = {}; + + /** + * Collection of installed plugins. These are included by default in PIXI, but can be excluded + * by creating a custom build. Consult the README for more information about creating custom + * builds and excluding plugins. + * @member {object} plugins + * @readonly + * @property {PIXI.AccessibilityManager} accessibility Support tabbing interactive elements. + */ +} + +extensions.handleByMap(ExtensionType.CanvasRendererPlugin, CanvasRenderer.__plugins); +extensions.handleByMap(ExtensionType.CanvasRendererSystem, CanvasRenderer.__systems); +extensions.add(CanvasRenderer); diff --git a/packages/canvas/canvas-renderer/src/canvasUtils.ts b/packages/canvas-renderer/src/canvasUtils.ts similarity index 94% rename from packages/canvas/canvas-renderer/src/canvasUtils.ts rename to packages/canvas-renderer/src/canvasUtils.ts index e44857e386c..0f27ba86a17 100644 --- a/packages/canvas/canvas-renderer/src/canvasUtils.ts +++ b/packages/canvas-renderer/src/canvasUtils.ts @@ -1,4 +1,4 @@ -import { hex2rgb, rgb2hex } from '@pixi/utils'; +import { settings, utils } from '@pixi/core'; import { canUseNewCanvasBlendModes } from './utils/canUseNewCanvasBlendModes'; import type { Texture } from '@pixi/core'; @@ -8,7 +8,6 @@ import type { Texture } from '@pixi/core'; * * Tinting with the CanvasRenderer involves creating a new canvas to use as a texture, * so be aware of the performance implications. - * * @namespace PIXI.canvasUtils * @memberof PIXI */ @@ -17,11 +16,11 @@ export const canvasUtils = { /** * Basically this method just needs a sprite and a color and tints the sprite with the given color. - * * @memberof PIXI.canvasUtils * @param {PIXI.Sprite} sprite - the sprite to tint + * @param sprite.texture * @param {number} color - the color to use to tint the sprite with - * @return {HTMLCanvasElement} The tinted canvas + * @returns {HTMLCanvasElement} The tinted canvas */ getTintedCanvas: (sprite: { texture: Texture }, color: number): HTMLCanvasElement | HTMLImageElement => { @@ -48,7 +47,7 @@ export const canvasUtils = { } else { - canvas = document.createElement('canvas'); + canvas = settings.ADAPTER.createCanvas(); } canvasUtils.tintMethod(texture, color, canvas); @@ -74,11 +73,10 @@ export const canvasUtils = { /** * Basically this method just needs a sprite and a color and tints the sprite with the given color. - * * @memberof PIXI.canvasUtils * @param {PIXI.Texture} texture - the sprite to tint * @param {number} color - the color to use to tint the sprite with - * @return {HTMLCanvasElement} The tinted canvas + * @returns {HTMLCanvasElement} The tinted canvas */ getTintedPattern: (texture: Texture, color: number): CanvasPattern => { @@ -96,7 +94,7 @@ export const canvasUtils = { } if (!canvasUtils.canvas) { - canvasUtils.canvas = document.createElement('canvas'); + canvasUtils.canvas = settings.ADAPTER.createCanvas(); } canvasUtils.tintMethod(texture, color, canvasUtils.canvas); pattern = canvasUtils.canvas.getContext('2d').createPattern(canvasUtils.canvas, 'repeat'); @@ -108,7 +106,6 @@ export const canvasUtils = { /** * Tint a texture using the 'multiply' operation. - * * @memberof PIXI.canvasUtils * @param {PIXI.Texture} texture - the texture to tint * @param {number} color - the color to use to tint the sprite with @@ -167,7 +164,6 @@ export const canvasUtils = { /** * Tint a texture using the 'overlay' operation. - * * @memberof PIXI.canvasUtils * @param {PIXI.Texture} texture - the texture to tint * @param {number} color - the color to use to tint the sprite with @@ -211,7 +207,6 @@ export const canvasUtils = { /** * Tint a texture pixel per pixel. - * * @memberof PIXI.canvasUtils * @param {PIXI.Texture} texture - the texture to tint * @param {number} color - the color to use to tint the sprite with @@ -246,7 +241,7 @@ export const canvasUtils = { ); context.restore(); - const rgbValues = hex2rgb(color); + const rgbValues = utils.hex2rgb(color); const r = rgbValues[0]; const g = rgbValues[1]; const b = rgbValues[2]; @@ -267,27 +262,25 @@ export const canvasUtils = { /** * Rounds the specified color according to the canvasUtils.cacheStepsPerColorChannel. - * * @memberof PIXI.canvasUtils * @param {number} color - the color to round, should be a hex color - * @return {number} The rounded color. + * @returns {number} The rounded color. */ roundColor: (color: number): number => { const step = canvasUtils.cacheStepsPerColorChannel; - const rgbValues = hex2rgb(color); + const rgbValues = utils.hex2rgb(color); rgbValues[0] = Math.min(255, (rgbValues[0] / step) * step); rgbValues[1] = Math.min(255, (rgbValues[1] / step) * step); rgbValues[2] = Math.min(255, (rgbValues[2] / step) * step); - return rgb2hex(rgbValues); + return utils.rgb2hex(rgbValues); }, /** * Number of steps which will be used as a cap when rounding colors. - * * @memberof PIXI.canvasUtils * @type {number} */ @@ -295,7 +288,6 @@ export const canvasUtils = { /** * Tint cache boolean flag. - * * @memberof PIXI.canvasUtils * @type {boolean} */ @@ -303,7 +295,6 @@ export const canvasUtils = { /** * Whether or not the Canvas BlendModes are supported, consequently the ability to tint using the multiply method. - * * @memberof PIXI.canvasUtils * @type {boolean} */ @@ -311,7 +302,6 @@ export const canvasUtils = { /** * The tinting method that will be used. - * * @memberof PIXI.canvasUtils * @type {Function} */ diff --git a/packages/canvas/canvas-renderer/src/index.ts b/packages/canvas-renderer/src/index.ts similarity index 53% rename from packages/canvas/canvas-renderer/src/index.ts rename to packages/canvas-renderer/src/index.ts index 71bc5ee8fb4..ab1279cd229 100644 --- a/packages/canvas/canvas-renderer/src/index.ts +++ b/packages/canvas-renderer/src/index.ts @@ -1,6 +1,7 @@ export * from './CanvasRenderer'; +export * from './CanvasMaskSystem'; +export * from './CanvasObjectRendererSystem'; +export * from './CanvasContextSystem'; export * from './utils/canUseNewCanvasBlendModes'; export * from './canvasUtils'; - -import './Renderer'; import './BaseTexture'; diff --git a/packages/canvas/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts b/packages/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts similarity index 77% rename from packages/canvas/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts rename to packages/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts index 1086306c163..d44ac612d6e 100644 --- a/packages/canvas/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts +++ b/packages/canvas-renderer/src/utils/canUseNewCanvasBlendModes.ts @@ -1,17 +1,14 @@ +import { settings } from '@pixi/core'; + /** * Creates a little colored canvas - * * @ignore * @param {string} color - The color to make the canvas - * @return {canvas} a small canvas element + * @returns {HTMLCanvasElement} a small canvas element */ function createColoredCanvas(color: string): HTMLCanvasElement { - const canvas = document.createElement('canvas'); - - canvas.width = 6; - canvas.height = 1; - + const canvas = settings.ADAPTER.createCanvas(6, 1); const context = canvas.getContext('2d'); context.fillStyle = color; @@ -22,9 +19,8 @@ function createColoredCanvas(color: string): HTMLCanvasElement /** * Checks whether the Canvas BlendModes are supported by the current browser - * * @private - * @return {boolean} whether they are supported + * @returns {boolean} whether they are supported */ export function canUseNewCanvasBlendModes(): boolean { @@ -36,11 +32,7 @@ export function canUseNewCanvasBlendModes(): boolean const magenta = createColoredCanvas('#ff00ff'); const yellow = createColoredCanvas('#ffff00'); - const canvas = document.createElement('canvas'); - - canvas.width = 6; - canvas.height = 1; - + const canvas = settings.ADAPTER.createCanvas(6, 1); const context = canvas.getContext('2d'); context.globalCompositeOperation = 'multiply'; diff --git a/packages/canvas/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts b/packages/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts similarity index 92% rename from packages/canvas/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts rename to packages/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts index 7037b92b4a0..d01fc0919f0 100644 --- a/packages/canvas/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts +++ b/packages/canvas-renderer/src/utils/mapCanvasBlendModesToPixi.ts @@ -1,15 +1,15 @@ -import { BLEND_MODES } from '@pixi/constants'; +import { BLEND_MODES } from '@pixi/core'; import { canUseNewCanvasBlendModes } from './canUseNewCanvasBlendModes'; /** * Maps blend combinations to Canvas. - * * @memberof PIXI * @function mapCanvasBlendModesToPixi * @private * @param {string[]} [array=[]] - The array to output into. - * @return {string[]} Mapped modes. + * @returns {string[]} Mapped modes. */ +// TODO after upgrading to typeScript 4.6, replace `string[]` with `GlobalCompositeOperation[]` export function mapCanvasBlendModesToPixi(array: string[] = []): string[] { if (canUseNewCanvasBlendModes()) @@ -28,7 +28,7 @@ export function mapCanvasBlendModesToPixi(array: string[] = []): string[] array[BLEND_MODES.DIFFERENCE] = 'difference'; array[BLEND_MODES.EXCLUSION] = 'exclusion'; array[BLEND_MODES.HUE] = 'hue'; - array[BLEND_MODES.SATURATION] = 'saturate'; + array[BLEND_MODES.SATURATION] = 'saturation'; array[BLEND_MODES.COLOR] = 'color'; array[BLEND_MODES.LUMINOSITY] = 'luminosity'; } diff --git a/packages/canvas/canvas-graphics/test/.eslintrc.json b/packages/canvas-renderer/test/.eslintrc.json similarity index 100% rename from packages/canvas/canvas-graphics/test/.eslintrc.json rename to packages/canvas-renderer/test/.eslintrc.json diff --git a/packages/canvas/canvas-renderer/test/CanvasMaskManager.tests.ts b/packages/canvas-renderer/test/CanvasMaskManager.tests.ts similarity index 54% rename from packages/canvas/canvas-renderer/test/CanvasMaskManager.tests.ts rename to packages/canvas-renderer/test/CanvasMaskManager.tests.ts index c8c37d3f8a4..577dc11615c 100644 --- a/packages/canvas/canvas-renderer/test/CanvasMaskManager.tests.ts +++ b/packages/canvas-renderer/test/CanvasMaskManager.tests.ts @@ -2,21 +2,20 @@ import { Container } from '@pixi/display'; import { Graphics } from '@pixi/graphics'; import { Sprite } from '@pixi/sprite'; import { CanvasRenderer } from '@pixi/canvas-renderer'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import '@pixi/canvas-display'; -describe('CanvasMaskManager', function () +describe('CanvasMaskManager', () => { - it('should work on all graphics masks inside container', function () + it('should work on all graphics masks inside container', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); - const shapeSpy = sinon.spy(renderer.maskManager, 'renderGraphicsShape'); - const contextPath = sinon.spy(renderer.context, 'closePath'); + const shapeSpy = jest.spyOn(renderer.maskManager, 'renderGraphicsShape'); + const contextPath = jest.spyOn(renderer.canvasContext.activeContext, 'closePath'); const cont = new Container(); cont.mask = new Sprite(); - expect(() => { renderer.render(cont); }).to.not.throw(); - expect(shapeSpy).to.not.called; + expect(() => { renderer.render(cont); }).not.toThrowError(); + expect(shapeSpy).not.toBeCalled(); const graphics1 = new Graphics(); const graphics2 = new Graphics(); @@ -30,20 +29,20 @@ describe('CanvasMaskManager', function () cont.mask.addChild(graphics1, graphics2); cont.addChild(cont.mask); - expect(() => { renderer.render(cont); }).to.not.throw(); - expect(shapeSpy).to.calledTwice; - expect(contextPath).to.calledTwice; + expect(() => { renderer.render(cont); }).not.toThrowError(); + expect(shapeSpy).toBeCalledTimes(2); + expect(contextPath).toBeCalledTimes(2); cont.mask.removeChildren(); cont.mask = graphics1; - expect(() => { renderer.render(cont); }).to.not.throw(); - expect(shapeSpy).to.calledThrice; - expect(contextPath).to.calledThrice; + expect(() => { renderer.render(cont); }).not.toThrowError(); + expect(shapeSpy).toBeCalledTimes(3); + expect(contextPath).toBeCalledTimes(3); }); - it('should set correct transform for graphics', function () + it('should set correct transform for graphics', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); - const transformSpy = sinon.spy(renderer.context, 'setTransform'); + const transformSpy = jest.spyOn(renderer.canvasContext.activeContext, 'setTransform'); const cont = new Container(); const graphics1 = new Graphics(); const graphics2 = new Graphics(); @@ -60,9 +59,9 @@ describe('CanvasMaskManager', function () cont.mask.addChild(graphics1, graphics2); cont.addChild(cont.mask); - expect(() => { renderer.render(cont); }).to.not.throw(); - expect(transformSpy).to.calledThrice; - expect(transformSpy.args[1][0]).to.equal(2.0); - expect(transformSpy.args[2][0]).to.equal(3.0); + expect(() => { renderer.render(cont); }).not.toThrowError(); + expect(transformSpy).toBeCalledTimes(3); + expect(transformSpy.mock.calls[1][0]).toEqual(2); + expect(transformSpy.mock.calls[2][0]).toEqual(3); }); }); diff --git a/packages/canvas/canvas-renderer/test/CanvasRenderer.tests.ts b/packages/canvas-renderer/test/CanvasRenderer.tests.ts similarity index 62% rename from packages/canvas/canvas-renderer/test/CanvasRenderer.tests.ts rename to packages/canvas-renderer/test/CanvasRenderer.tests.ts index 99300673887..356267acb74 100644 --- a/packages/canvas/canvas-renderer/test/CanvasRenderer.tests.ts +++ b/packages/canvas-renderer/test/CanvasRenderer.tests.ts @@ -1,17 +1,17 @@ import { Container } from '@pixi/display'; -import { Matrix } from '@pixi/math'; +import { Matrix } from '@pixi/core'; import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { expect } from 'chai'; +import '@pixi/canvas-display'; -describe('CanvasRenderer', function () +describe('CanvasRenderer', () => { - it('should default context to rootContext', function () + it('should default context to rootContext', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); try { - expect(renderer.context).to.equal(renderer.rootContext); + expect(renderer.canvasContext.activeContext).toEqual(renderer.canvasContext.rootContext); } finally { @@ -19,7 +19,7 @@ describe('CanvasRenderer', function () } }); - it('should allow clear() to work despite no containers added to the renderer', function () + it('should allow clear() to work despite no containers added to the renderer', () => { const renderer = new CanvasRenderer({ width: 1, height: 1 }); @@ -33,7 +33,7 @@ describe('CanvasRenderer', function () } }); - it('should update transform in case of temp parent', function () + it('should update transform in case of temp parent', () => { // this test works only for CanvasRenderer, WebGLRenderer behaviour is different const renderer = new CanvasRenderer({ width: 1, height: 1 }); @@ -44,15 +44,15 @@ describe('CanvasRenderer', function () par.addChild(cont); renderer.render(cont, { transform: new Matrix().translate(10, 20) }); - expect(cont.worldTransform.tx).to.equal(0); - expect(cont.worldTransform.ty).to.equal(0); + expect(cont.worldTransform.tx).toEqual(0); + expect(cont.worldTransform.ty).toEqual(0); renderer.render(par); - expect(cont.worldTransform.tx).to.equal(5); - expect(cont.worldTransform.ty).to.equal(10); + expect(cont.worldTransform.tx).toEqual(5); + expect(cont.worldTransform.ty).toEqual(10); renderer.render(cont, { transform: new Matrix().translate(-20, 30) }); - expect(cont.worldTransform.tx).to.equal(0); - expect(cont.worldTransform.ty).to.equal(0); + expect(cont.worldTransform.tx).toEqual(0); + expect(cont.worldTransform.ty).toEqual(0); }); }); diff --git a/packages/filters/filter-alpha/LICENSE b/packages/canvas-sprite-tiling/LICENSE similarity index 100% rename from packages/filters/filter-alpha/LICENSE rename to packages/canvas-sprite-tiling/LICENSE diff --git a/packages/canvas/canvas-sprite-tiling/README.md b/packages/canvas-sprite-tiling/README.md similarity index 100% rename from packages/canvas/canvas-sprite-tiling/README.md rename to packages/canvas-sprite-tiling/README.md diff --git a/packages/canvas-sprite-tiling/global.d.ts b/packages/canvas-sprite-tiling/global.d.ts new file mode 100644 index 00000000000..011547f89f3 --- /dev/null +++ b/packages/canvas-sprite-tiling/global.d.ts @@ -0,0 +1,7 @@ +declare namespace GlobalMixins +{ + interface TilingSprite + { + _canvasPattern: CanvasPattern; + } +} diff --git a/packages/canvas/canvas-sprite-tiling/package.json b/packages/canvas-sprite-tiling/package.json similarity index 51% rename from packages/canvas/canvas-sprite-tiling/package.json rename to packages/canvas-sprite-tiling/package.json index d250e6a5e1e..6774d2c9817 100644 --- a/packages/canvas/canvas-sprite-tiling/package.json +++ b/packages/canvas-sprite-tiling/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/canvas-sprite-tiling", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-sprite-tiling.js", - "module": "dist/esm/canvas-sprite-tiling.js", - "bundle": "dist/browser/canvas-sprite-tiling.js", - "bundleNoExports": true, + "module": "dist/esm/canvas-sprite-tiling.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-sprite-tiling.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-sprite-tiling.js" + } + } + }, "description": "Canvas mixin for the sprite-tiling package", "author": "Mat Groves", "contributors": [ @@ -21,15 +32,13 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite-tiling": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-renderer", + "@pixi/canvas-sprite", + "@pixi/core", + "@pixi/sprite-tiling" + ] } diff --git a/packages/canvas/canvas-sprite-tiling/src/TilingSprite.ts b/packages/canvas-sprite-tiling/src/TilingSprite.ts similarity index 93% rename from packages/canvas/canvas-sprite-tiling/src/TilingSprite.ts rename to packages/canvas-sprite-tiling/src/TilingSprite.ts index 4aca4c62a84..fb17854f3f6 100644 --- a/packages/canvas/canvas-sprite-tiling/src/TilingSprite.ts +++ b/packages/canvas-sprite-tiling/src/TilingSprite.ts @@ -1,7 +1,6 @@ import { TilingSprite } from '@pixi/sprite-tiling'; import { canvasUtils } from '@pixi/canvas-renderer'; -import { CanvasRenderTarget } from '@pixi/utils'; -import { Matrix, Point } from '@pixi/math'; +import { Matrix, Point, utils } from '@pixi/core'; import type { CanvasRenderer } from '@pixi/canvas-renderer'; @@ -11,7 +10,6 @@ const patternRect = [new Point(), new Point(), new Point(), new Point()]; /** * Renders the object using the Canvas renderer - * * @protected * @function _renderCanvas * @memberof PIXI.TilingSprite# @@ -26,7 +24,7 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe return; } - const context = renderer.context; + const context = renderer.canvasContext.activeContext; const transform = this.worldTransform; const baseTexture = texture.baseTexture; const source = baseTexture.getDrawableSource(); @@ -37,7 +35,7 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe { this._textureID = this._texture._updateID; // cut an object from a spritesheet.. - const tempCanvas = new CanvasRenderTarget(texture._frame.width, + const tempCanvas = new utils.CanvasRenderTarget(texture._frame.width, texture._frame.height, baseTextureResolution); @@ -58,7 +56,7 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe // set context state.. context.globalAlpha = this.worldAlpha; - renderer.setBlendMode(this.blendMode); + renderer.canvasContext.setBlendMode(this.blendMode); this.tileTransform.updateLocalTransform(); const lt = this.tileTransform.localTransform; @@ -101,7 +99,7 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe * * Local Space (-localBounds.x, -localBounds.y) <--> Pattern Space (0, 0) * - * Here the mapping is provided by the tileTransfrom PLUS some "shift". This shift is done POST-tileTransform. The shift + * Here the mapping is provided by the tileTransform PLUS some "shift". This shift is done POST-tileTransform. The shift * is equal to the position of the top-left corner of the tiling sprite in its local space. * * Hence, @@ -111,14 +109,14 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe // worldMatrix is used to convert from pattern space to world space. // - // worldMatrix = tileTransform x shiftTransform x worldTransfrom + // worldMatrix = tileTransform x shiftTransform x worldTransform // = patternMatrix x worldTransform worldMatrix.identity(); // patternMatrix is used to convert from pattern space to local space. The drawing commands are issued in pattern space // and this matrix is used to inverse-map the local space vertices into it. // - // patternMatrix = tileTransfrom x shiftTransform + // patternMatrix = tileTransform x shiftTransform patternMatrix.copyFrom(lt); // Apply shiftTransform into patternMatrix. See $1.1 @@ -131,7 +129,7 @@ TilingSprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRe worldMatrix.prepend(patternMatrix); worldMatrix.prepend(transform); - renderer.setContextTransform(worldMatrix); + renderer.canvasContext.setContextTransform(worldMatrix); // Fill the pattern! context.fillStyle = this._canvasPattern; diff --git a/packages/canvas/canvas-sprite-tiling/src/index.ts b/packages/canvas-sprite-tiling/src/index.ts similarity index 100% rename from packages/canvas/canvas-sprite-tiling/src/index.ts rename to packages/canvas-sprite-tiling/src/index.ts diff --git a/packages/canvas/canvas-text/LICENSE b/packages/canvas-sprite/LICENSE similarity index 100% rename from packages/canvas/canvas-text/LICENSE rename to packages/canvas-sprite/LICENSE diff --git a/packages/canvas-sprite/README.md b/packages/canvas-sprite/README.md new file mode 100644 index 00000000000..cb0ce573d0c --- /dev/null +++ b/packages/canvas-sprite/README.md @@ -0,0 +1,13 @@ +# @pixi/canvas-sprite + +## Installation + +```bash +npm install @pixi/canvas-sprite +``` + +## Usage + +```js +import '@pixi/canvas-sprite'; +``` \ No newline at end of file diff --git a/packages/canvas-sprite/global.d.ts b/packages/canvas-sprite/global.d.ts new file mode 100644 index 00000000000..77592778c66 --- /dev/null +++ b/packages/canvas-sprite/global.d.ts @@ -0,0 +1,8 @@ +declare namespace GlobalMixins +{ + interface Sprite + { + _tintedCanvas: HTMLCanvasElement | HTMLImageElement; + _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; + } +} diff --git a/packages/canvas/canvas-sprite/package.json b/packages/canvas-sprite/package.json similarity index 52% rename from packages/canvas/canvas-sprite/package.json rename to packages/canvas-sprite/package.json index 6fb5036caa9..97eb117be0c 100644 --- a/packages/canvas/canvas-sprite/package.json +++ b/packages/canvas-sprite/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/canvas-sprite", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-sprite.js", - "module": "dist/esm/canvas-sprite.js", - "bundle": "dist/browser/canvas-sprite.js", + "module": "dist/esm/canvas-sprite.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-sprite.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-sprite.js" + } + } + }, "description": "Canvas mixin for the sprite package", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,13 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/constants": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-display", + "@pixi/canvas-renderer", + "@pixi/core", + "@pixi/sprite" + ] } diff --git a/packages/canvas/canvas-sprite/src/CanvasSpriteRenderer.ts b/packages/canvas-sprite/src/CanvasSpriteRenderer.ts similarity index 65% rename from packages/canvas/canvas-sprite/src/CanvasSpriteRenderer.ts rename to packages/canvas-sprite/src/CanvasSpriteRenderer.ts index 737867f8549..559d14911fb 100644 --- a/packages/canvas/canvas-sprite/src/CanvasSpriteRenderer.ts +++ b/packages/canvas-sprite/src/CanvasSpriteRenderer.ts @@ -1,8 +1,9 @@ -import { SCALE_MODES, BLEND_MODES } from '@pixi/constants'; -import { Matrix, groupD8 } from '@pixi/math'; +import { SCALE_MODES, BLEND_MODES, extensions, ExtensionType, Matrix, groupD8 } from '@pixi/core'; import { canvasUtils } from '@pixi/canvas-renderer'; + import type { CanvasRenderer } from '@pixi/canvas-renderer'; import type { Sprite } from '@pixi/sprite'; +import type { ExtensionMetadata } from '@pixi/core'; const canvasRenderWorldTransform = new Matrix(); @@ -26,13 +27,18 @@ const canvasRenderWorldTransform = new Matrix(); /** * Renderer dedicated to drawing and batching sprites. - * * @class * @protected * @memberof PIXI */ export class CanvasSpriteRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'sprite', + type: ExtensionType.CanvasRendererPlugin, + }; + /** A reference to the current renderer */ protected renderer: CanvasRenderer; @@ -44,22 +50,31 @@ export class CanvasSpriteRenderer /** * Renders the sprite object. - * * @param sprite - the sprite to render when using this spritebatch */ render(sprite: Sprite): void { const texture = sprite._texture; const renderer = this.renderer; - const context = renderer.context; + const context = renderer.canvasContext.activeContext; + const activeResolution = renderer.canvasContext.activeResolution; if (!texture.valid) { return; } - const width = texture._frame.width; - const height = texture._frame.height; + const sourceWidth = texture._frame.width; + const sourceHeight = texture._frame.height; + + let destWidth = texture._frame.width; + let destHeight = texture._frame.height; + + if (texture.trim) + { + destWidth = texture.trim.width; + destHeight = texture.trim.height; + } let wt = sprite.transform.worldTransform; let dx = 0; @@ -72,17 +87,18 @@ export class CanvasSpriteRenderer return; } - renderer.setBlendMode(sprite.blendMode, true); + renderer.canvasContext.setBlendMode(sprite.blendMode, true); - renderer.context.globalAlpha = sprite.worldAlpha; + context.globalAlpha = sprite.worldAlpha; // If smoothingEnabled is supported and we need to change the smoothing property for sprite texture const smoothingEnabled = texture.baseTexture.scaleMode === SCALE_MODES.LINEAR; + const smoothProperty = renderer.canvasContext.smoothProperty; - if (renderer.smoothProperty - && renderer.context[renderer.smoothProperty] !== smoothingEnabled) + if (smoothProperty + && context[smoothProperty] !== smoothingEnabled) { - context[renderer.smoothProperty] = smoothingEnabled; + context[smoothProperty] = smoothingEnabled; } if (texture.trim) @@ -106,10 +122,10 @@ export class CanvasSpriteRenderer dy = 0; } - dx -= width / 2; - dy -= height / 2; + dx -= destWidth / 2; + dy -= destHeight / 2; - renderer.setContextTransform(wt, sprite.roundPixels, 1); + renderer.canvasContext.setContextTransform(wt, sprite.roundPixels, 1); // Allow for pixel rounding if (sprite.roundPixels) { @@ -118,17 +134,18 @@ export class CanvasSpriteRenderer } const resolution = texture.baseTexture.resolution; - const outerBlend = renderer._outerBlend; + + const outerBlend = renderer.canvasContext._outerBlend; if (outerBlend) { context.save(); context.beginPath(); context.rect( - dx * renderer.resolution, - dy * renderer.resolution, - width * renderer.resolution, - height * renderer.resolution + dx * activeResolution, + dy * activeResolution, + destWidth * activeResolution, + destHeight * activeResolution ); context.clip(); } @@ -147,12 +164,12 @@ export class CanvasSpriteRenderer sprite._tintedCanvas, 0, 0, - Math.floor(width * resolution), - Math.floor(height * resolution), - Math.floor(dx * renderer.resolution), - Math.floor(dy * renderer.resolution), - Math.floor(width * renderer.resolution), - Math.floor(height * renderer.resolution) + Math.floor(sourceWidth * resolution), + Math.floor(sourceHeight * resolution), + Math.floor(dx * activeResolution), + Math.floor(dy * activeResolution), + Math.floor(destWidth * activeResolution), + Math.floor(destHeight * activeResolution) ); } else @@ -161,12 +178,12 @@ export class CanvasSpriteRenderer source, texture._frame.x * resolution, texture._frame.y * resolution, - Math.floor(width * resolution), - Math.floor(height * resolution), - Math.floor(dx * renderer.resolution), - Math.floor(dy * renderer.resolution), - Math.floor(width * renderer.resolution), - Math.floor(height * renderer.resolution) + Math.floor(sourceWidth * resolution), + Math.floor(sourceHeight * resolution), + Math.floor(dx * activeResolution), + Math.floor(dy * activeResolution), + Math.floor(destWidth * activeResolution), + Math.floor(destHeight * activeResolution) ); } @@ -175,7 +192,7 @@ export class CanvasSpriteRenderer context.restore(); } // just in case, leaking outer blend here will be catastrophic! - renderer.setBlendMode(BLEND_MODES.NORMAL); + renderer.canvasContext.setBlendMode(BLEND_MODES.NORMAL); } /** destroy the sprite object */ @@ -184,3 +201,5 @@ export class CanvasSpriteRenderer this.renderer = null; } } + +extensions.add(CanvasSpriteRenderer); diff --git a/packages/canvas/canvas-sprite/src/Sprite.ts b/packages/canvas-sprite/src/Sprite.ts similarity index 70% rename from packages/canvas/canvas-sprite/src/Sprite.ts rename to packages/canvas-sprite/src/Sprite.ts index a57f0e0d3e3..698fe198e93 100644 --- a/packages/canvas/canvas-sprite/src/Sprite.ts +++ b/packages/canvas-sprite/src/Sprite.ts @@ -10,13 +10,12 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; Sprite.prototype._tintedCanvas = null; /** -* Renders the object using the Canvas renderer -* -* @private -* @method _renderCanvas -* @memberof PIXI.Sprite# -* @param {PIXI.CanvasRenderer} renderer - The renderer -*/ + * Renders the object using the Canvas renderer + * @private + * @method _renderCanvas + * @memberof PIXI.Sprite# + * @param {PIXI.CanvasRenderer} renderer - The renderer + */ Sprite.prototype._renderCanvas = function _renderCanvas(renderer: CanvasRenderer): void { renderer.plugins.sprite.render(this); diff --git a/packages/canvas/canvas-sprite/src/index.ts b/packages/canvas-sprite/src/index.ts similarity index 100% rename from packages/canvas/canvas-sprite/src/index.ts rename to packages/canvas-sprite/src/index.ts diff --git a/packages/canvas/canvas-display/test/.eslintrc.json b/packages/canvas-sprite/test/.eslintrc.json similarity index 100% rename from packages/canvas/canvas-display/test/.eslintrc.json rename to packages/canvas-sprite/test/.eslintrc.json diff --git a/packages/canvas-sprite/test/CanvasSpriteRenderer.tests.ts b/packages/canvas-sprite/test/CanvasSpriteRenderer.tests.ts new file mode 100644 index 00000000000..490e28bea5e --- /dev/null +++ b/packages/canvas-sprite/test/CanvasSpriteRenderer.tests.ts @@ -0,0 +1,146 @@ +import '@pixi/canvas-display'; +import { CanvasRenderer } from '@pixi/canvas-renderer'; +import { MIPMAP_MODES, SCALE_MODES, Rectangle, BaseTexture, CanvasResource, Texture } from '@pixi/core'; +import { Container } from '@pixi/display'; +import { Sprite } from '@pixi/sprite'; +import '@pixi/canvas-sprite'; + +describe('CanvasSpriteRenderer', () => +{ + it('should still render a sprite after texture is destroyed', () => + { + const renderer = new CanvasRenderer({ width: 1, height: 1 }); + const texture = Texture.WHITE; + const sprite = new Sprite(texture); + + renderer.render(sprite); + texture.destroy(); + + try + { + expect(() => { renderer.render(sprite); }).not.toThrowError(); + } + finally + { + renderer.destroy(); + } + }); + + it('should scale the base texture correctly using a trimmed rect', () => + { + // create 2x1 texture, left pixel red, right pixel green + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + + canvas.width = 2; + canvas.height = 1; + + context.fillStyle = '#ff0000'; + context.fillRect(0, 0, 1, 1); + + context.fillStyle = '#00ff00'; + context.fillRect(1, 0, 1, 1); + + const baseTexture = new BaseTexture(new CanvasResource(canvas), { + mipmap: MIPMAP_MODES.OFF, + scaleMode: SCALE_MODES.NEAREST + }); + + // set a scale value to orig and trim rectangle to scale the texture + const scale = 2; + + const frame = new Rectangle(0, 0, baseTexture.width, baseTexture.height); + const orig = new Rectangle(0, 0, baseTexture.width * scale, baseTexture.height * scale); + const trim = new Rectangle(0, 0, baseTexture.width * scale, baseTexture.height * scale); + + const testSprite = new Sprite(new Texture(baseTexture, frame, orig, trim)); + + const stage = new Container(); + + stage.addChild(testSprite); + + const renderer = new CanvasRenderer(); + + renderer.render(stage); + + const ctx = renderer.view.getContext('2d'); + + const pixels = ctx.getImageData(0, 0, 2 * scale, Number(scale)).data; + + expect(pixels[0]).toEqual(255); + expect(pixels[1]).toEqual(0); + expect(pixels[2]).toEqual(0); + expect(pixels[3]).toEqual(255); + + expect(pixels[8]).toEqual(0); + expect(pixels[9]).toEqual(255); + expect(pixels[10]).toEqual(0); + expect(pixels[11]).toEqual(255); + }); + + it('should render a sprite with a rotated base texture correctly', () => + { + // create a 4x2 texture, left 2x2 red, right 2x2 green + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + + canvas.width = 4; + canvas.height = 2; + + context.fillStyle = '#ff0000'; + context.fillRect(0, 0, 2, 2); + + context.fillStyle = '#00ff00'; + context.fillRect(2, 0, 2, 2); + + const baseTexture = new BaseTexture(new CanvasResource(canvas), { + mipmap: MIPMAP_MODES.OFF, + scaleMode: SCALE_MODES.NEAREST + }); + + const frame = new Rectangle(0, 0, 4, 2); + const orig = new Rectangle(0, 0, 2, 4); + + // create a sprite with a texture that treats this base texture as rotated + // (now a 2x4 texture with the top 2x2 green, bottom 2x2 red) + const testSprite = new Sprite(new Texture(baseTexture, frame, orig, null, 2)); + + const stage = new Container(); + + stage.addChild(testSprite); + + const renderer = new CanvasRenderer(); + + renderer.render(stage); + + const ctx = renderer.view.getContext('2d'); + + // grab 2x2 pixels from corner where the two 2x2s meet on the right edge, + // so we can check nothing is rendering wider than it should + const pixels = ctx.getImageData(1, 1, 2, 2).data; + + // the top left pixel should be green + expect(pixels[0]).toEqual(0); + expect(pixels[1]).toEqual(255); + expect(pixels[2]).toEqual(0); + expect(pixels[3]).toEqual(255); + + // the top right pixel should be black (not being rendered to) + expect(pixels[4]).toEqual(0); + expect(pixels[5]).toEqual(0); + expect(pixels[6]).toEqual(0); + expect(pixels[7]).toEqual(255); + + // the bottom left pixel should be red + expect(pixels[8]).toEqual(255); + expect(pixels[9]).toEqual(0); + expect(pixels[10]).toEqual(0); + expect(pixels[11]).toEqual(255); + + // the bottom right pixel should also black (not being rendered to) + expect(pixels[12]).toEqual(0); + expect(pixels[13]).toEqual(0); + expect(pixels[14]).toEqual(0); + expect(pixels[15]).toEqual(255); + }); +}); diff --git a/packages/canvas/canvas-sprite/LICENSE b/packages/canvas-text/LICENSE similarity index 100% rename from packages/canvas/canvas-sprite/LICENSE rename to packages/canvas-text/LICENSE diff --git a/packages/canvas/canvas-text/README.md b/packages/canvas-text/README.md similarity index 100% rename from packages/canvas/canvas-text/README.md rename to packages/canvas-text/README.md diff --git a/packages/canvas/canvas-text/package.json b/packages/canvas-text/package.json similarity index 50% rename from packages/canvas/canvas-text/package.json rename to packages/canvas-text/package.json index 368008f81a9..84a08ba9540 100644 --- a/packages/canvas/canvas-text/package.json +++ b/packages/canvas-text/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/canvas-text", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/canvas-text.js", - "module": "dist/esm/canvas-text.js", - "bundle": "dist/browser/canvas-text.js", - "bundleNoExports": true, + "module": "dist/esm/canvas-text.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/canvas-text.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/canvas-text.js" + } + } + }, "description": "Canvas mixin for the text package", "author": "Dave Moore", "homepage": "http://pixijs.com/", @@ -18,13 +29,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/canvas-sprite": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/text": "6.3.0" - } + "pixiRequirements": [ + "@pixi/canvas-sprite", + "@pixi/sprite", + "@pixi/text" + ] } diff --git a/packages/canvas/canvas-text/src/Text.ts b/packages/canvas-text/src/Text.ts similarity index 99% rename from packages/canvas/canvas-text/src/Text.ts rename to packages/canvas-text/src/Text.ts index f4f730d426d..c71bed83801 100644 --- a/packages/canvas/canvas-text/src/Text.ts +++ b/packages/canvas-text/src/Text.ts @@ -5,7 +5,6 @@ import type { CanvasRenderer } from '@pixi/canvas-renderer'; /** * Renders the object using the Canvas renderer - * * @method _renderCanvas * @memberof PIXI.Text# * @private diff --git a/packages/canvas/canvas-text/src/index.ts b/packages/canvas-text/src/index.ts similarity index 100% rename from packages/canvas/canvas-text/src/index.ts rename to packages/canvas-text/src/index.ts diff --git a/packages/canvas/canvas-display/LICENSE b/packages/canvas/canvas-display/LICENSE deleted file mode 100644 index 148e3eb97d9..00000000000 --- a/packages/canvas/canvas-display/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2013-2018 Mathew Groves, Chad Engler - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/packages/canvas/canvas-display/global.d.ts b/packages/canvas/canvas-display/global.d.ts deleted file mode 100644 index 5854bc9e9fa..00000000000 --- a/packages/canvas/canvas-display/global.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare namespace GlobalMixins { - interface Container { - _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; - } -} diff --git a/packages/canvas/canvas-display/test/Container.tests.ts b/packages/canvas/canvas-display/test/Container.tests.ts deleted file mode 100644 index 8f5d3f53f55..00000000000 --- a/packages/canvas/canvas-display/test/Container.tests.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Container } from '@pixi/display'; -import sinon from 'sinon'; -import { expect } from 'chai'; - -import '@pixi/canvas-display'; - -describe('Container', function () -{ - describe('render', function () - { - it('should not render when object not visible', function () - { - const container = new Container(); - const canvasSpy = sinon.spy(container._renderCanvas); - - container.visible = false; - - container.renderCanvas(); - expect(canvasSpy).to.not.have.been.called; - }); - - it('should not render when alpha is zero', function () - { - const container = new Container(); - const canvasSpy = sinon.spy(container._renderCanvas); - - container.worldAlpha = 0; - - container.renderCanvas(); - expect(canvasSpy).to.not.have.been.called; - }); - - it('should not render when object not renderable', function () - { - const container = new Container(); - const canvasSpy = sinon.spy(container._renderCanvas); - - container.renderable = false; - - container.renderCanvas(); - expect(canvasSpy).to.not.have.been.called; - }); - - it('should render children', function () - { - const container = new Container(); - const child = new Container(); - const canvasSpy = sinon.spy(child, '_renderCanvas'); - - container.addChild(child); - - container.renderCanvas(); - expect(canvasSpy).to.have.been.called; - }); - }); -}); diff --git a/packages/canvas/canvas-extract/README.md b/packages/canvas/canvas-extract/README.md deleted file mode 100644 index 2a6b71597a8..00000000000 --- a/packages/canvas/canvas-extract/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/canvas-extract - -## Installation - -```bash -npm install @pixi/canvas-extract -``` - -## Usage - -```js -import { CanvasExtract } from '@pixi/canvas-extract'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; - -CanvasRenderer.registerPlugin('extract', CanvasExtract); -``` \ No newline at end of file diff --git a/packages/canvas/canvas-extract/test/CanvasExtract.tests.ts b/packages/canvas/canvas-extract/test/CanvasExtract.tests.ts deleted file mode 100644 index b91b3b7658b..00000000000 --- a/packages/canvas/canvas-extract/test/CanvasExtract.tests.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { CanvasExtract } from '@pixi/canvas-extract'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { Sprite } from '@pixi/sprite'; -import { expect } from 'chai'; -import { skipHello } from '@pixi/utils'; -import { Texture, RenderTexture } from '@pixi/core'; -import { CanvasSpriteRenderer } from '@pixi/canvas-sprite'; - -import '@pixi/canvas-display'; - -skipHello(); - -describe('CanvasExtract', function () -{ - before(function () - { - CanvasRenderer.registerPlugin('extract', CanvasExtract); - CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer); - }); - - it('should access extract on renderer', function () - { - const renderer = new CanvasRenderer(); - - expect(renderer.plugins.extract).to.be.an.instanceof(CanvasExtract); - - renderer.destroy(); - }); - - it('should extract an sprite', function () - { - const renderer = new CanvasRenderer(); - const sprite = new Sprite(Texture.WHITE); - const extract = renderer.plugins.extract as CanvasExtract; - - expect(extract.canvas(sprite)).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64(sprite)).to.be.a('string'); - expect(extract.pixels(sprite)).to.be.instanceOf(Uint8ClampedArray); - expect(extract.image(sprite)).to.be.instanceOf(HTMLImageElement); - - renderer.destroy(); - sprite.destroy(); - }); - - it('should extract with no arguments', function () - { - const renderer = new CanvasRenderer(); - const extract = renderer.plugins.extract as CanvasExtract; - - expect(extract.canvas()).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64()).to.be.a('string'); - expect(extract.pixels()).to.be.instanceOf(Uint8ClampedArray); - expect(extract.image()).to.be.instanceOf(HTMLImageElement); - - renderer.destroy(); - }); - - it('should extract a render texture', function () - { - const renderer = new CanvasRenderer(); - const extract = renderer.plugins.extract as CanvasExtract; - const renderTexture = RenderTexture.create({ width: 10, height: 10 }); - const sprite = new Sprite(Texture.WHITE); - - renderer.render(sprite, { renderTexture }); - - expect(extract.canvas(renderTexture)).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64(renderTexture)).to.be.a('string'); - expect(extract.pixels(renderTexture)).to.be.instanceOf(Uint8ClampedArray); - expect(extract.image(renderTexture)).to.be.instanceOf(HTMLImageElement); - - renderer.destroy(); - renderTexture.destroy(); - sprite.destroy(); - }); -}); diff --git a/packages/canvas/canvas-graphics/README.md b/packages/canvas/canvas-graphics/README.md deleted file mode 100644 index 67c2b3a08fc..00000000000 --- a/packages/canvas/canvas-graphics/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/canvas-graphics - -## Installation - -```bash -npm install @pixi/canvas-graphics -``` - -## Usage - -```js -import { CanvasGraphicsRenderer } from '@pixi/canvas-graphics'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; - -CanvasRenderer.registerPlugin('graphics', CanvasGraphicsRenderer); -``` \ No newline at end of file diff --git a/packages/canvas/canvas-graphics/global.d.ts b/packages/canvas/canvas-graphics/global.d.ts deleted file mode 100644 index 183cc55a3ae..00000000000 --- a/packages/canvas/canvas-graphics/global.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare namespace GlobalMixins { - interface Graphics { - _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; - generateCanvasTexture(scaleMode: import('@pixi/constants').SCALE_MODES, resolution?: number): Texture; - cachedGraphicsData: import('@pixi/graphics').GraphicsData[]; - } -} diff --git a/packages/canvas/canvas-mesh/README.md b/packages/canvas/canvas-mesh/README.md deleted file mode 100644 index 085cdca5a11..00000000000 --- a/packages/canvas/canvas-mesh/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/canvas-mesh - -## Installation - -```bash -npm install @pixi/canvas-mesh -``` - -## Usage - -```js -import { CanvasMeshRenderer } from '@pixi/canvas-mesh'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; - -CanvasRenderer.registerPlugin('mesh', CanvasMeshRenderer); -``` \ No newline at end of file diff --git a/packages/canvas/canvas-prepare/README.md b/packages/canvas/canvas-prepare/README.md deleted file mode 100644 index c0074c9ba86..00000000000 --- a/packages/canvas/canvas-prepare/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/canvas-prepare - -## Installation - -```bash -npm install @pixi/canvas-prepare -``` - -## Usage - -```js -import { CanvasPrepare } from '@pixi/canvas-prepare'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; - -CanvasRenderer.registerPlugin('prepare', CanvasPrepare); -``` \ No newline at end of file diff --git a/packages/canvas/canvas-renderer/src/CanvasRenderer.ts b/packages/canvas/canvas-renderer/src/CanvasRenderer.ts deleted file mode 100644 index 7e85b46a404..00000000000 --- a/packages/canvas/canvas-renderer/src/CanvasRenderer.ts +++ /dev/null @@ -1,494 +0,0 @@ -import { AbstractRenderer, CanvasResource, RenderTexture, BaseRenderTexture } from '@pixi/core'; -import { CanvasRenderTarget, sayHello, rgb2hex, hex2string, deprecation } from '@pixi/utils'; -import { CanvasMaskManager } from './utils/CanvasMaskManager'; -import { mapCanvasBlendModesToPixi } from './utils/mapCanvasBlendModesToPixi'; -import { RENDERER_TYPE, SCALE_MODES, BLEND_MODES } from '@pixi/constants'; -import { settings } from '@pixi/settings'; -import { Matrix } from '@pixi/math'; - -import type { DisplayObject } from '@pixi/display'; -import type { - IRendererOptions, - IRendererPlugin, - IRendererPlugins, - IRendererRenderOptions -} from '@pixi/core'; - -const tempMatrix = new Matrix(); - -export interface ICanvasRendererPluginConstructor { - new (renderer: CanvasRenderer, options?: any): IRendererPlugin; -} - -export interface ICanvasRendererPlugins -{ - [key: string]: any; -} - -/* - * Different browsers support different smoothing property names - * this is the list of all platform props. - */ -type SmoothingEnabledProperties = - 'imageSmoothingEnabled' | - 'webkitImageSmoothingEnabled' | - 'mozImageSmoothingEnabled' | - 'oImageSmoothingEnabled' | - 'msImageSmoothingEnabled'; - -/** - * Rendering context for all browsers. This includes platform-specific - * properties that are not included in the spec for CanvasRenderingContext2D - * @private - */ -export interface CrossPlatformCanvasRenderingContext2D extends CanvasRenderingContext2D -{ - webkitImageSmoothingEnabled: boolean; - mozImageSmoothingEnabled: boolean; - oImageSmoothingEnabled: boolean; - msImageSmoothingEnabled: boolean; -} - -/** - * The CanvasRenderer draws the scene and all its content onto a 2d canvas. - * - * This renderer should be used for browsers that do not support WebGL. - * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything! - * - * @class - * @memberof PIXI - * @extends PIXI.AbstractRenderer - */ -export class CanvasRenderer extends AbstractRenderer -{ - /** - * Fired after rendering finishes. - * @event PIXI.CanvasRenderer#postrender - */ - /** - * Fired before rendering starts. - * @event PIXI.CanvasRenderer#prerender - */ - - /** The root canvas 2d context that everything is drawn with. */ - public readonly rootContext: CrossPlatformCanvasRenderingContext2D; - /** The currently active canvas 2d context (could change with renderTextures) */ - public context: CrossPlatformCanvasRenderingContext2D; - /** Boolean flag controlling canvas refresh. */ - public refresh = true; - /** - * Instance of a CanvasMaskManager, handles masking when using the canvas renderer. - * @member {PIXI.CanvasMaskManager} - */ - public maskManager: CanvasMaskManager = new CanvasMaskManager(this); - /** The canvas property used to set the canvas smoothing property. */ - public smoothProperty: SmoothingEnabledProperties = 'imageSmoothingEnabled'; - /** Tracks the blend modes useful for this renderer. */ - public readonly blendModes: string[] = mapCanvasBlendModesToPixi(); - public renderingToScreen = false; - - private _activeBlendMode: BLEND_MODES =null; - /** Projection transform, passed in render() stored here */ - private _projTransform: Matrix = null; - - /** @private */ - _outerBlend = false; - - /** - * @param options - The optional renderer parameters - * @param {number} [options.width=800] - the width of the screen - * @param {number} [options.height=600] - the height of the screen - * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional - * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property. - * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the - * canvas needs to be opaque, possibly for performance reasons on some older devices. - * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for - * resolutions other than 1 - * @param {boolean} [options.antialias=false] - sets antialias - * @param {number} [options.resolution=PIXI.settings.RESOLUTION] - The resolution / device pixel ratio of the renderer. - * @param {boolean} [options.preserveDrawingBuffer=false] - enables drawing buffer preservation, - * enable this if you need to call toDataUrl on the webgl context. - * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or - * not before the new render pass. - * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area - * (shown if not transparent). - * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque). - */ - constructor(options?: IRendererOptions) - { - super(RENDERER_TYPE.CANVAS, options); - - this.rootContext = this.view.getContext('2d', { alpha: this.useContextAlpha }) as - CrossPlatformCanvasRenderingContext2D; - - this.context = this.rootContext; - - if (!this.rootContext.imageSmoothingEnabled) - { - const rc = this.rootContext; - - if (rc.webkitImageSmoothingEnabled) - { - this.smoothProperty = 'webkitImageSmoothingEnabled'; - } - else if (rc.mozImageSmoothingEnabled) - { - this.smoothProperty = 'mozImageSmoothingEnabled'; - } - else if (rc.oImageSmoothingEnabled) - { - this.smoothProperty = 'oImageSmoothingEnabled'; - } - else if (rc.msImageSmoothingEnabled) - { - this.smoothProperty = 'msImageSmoothingEnabled'; - } - } - - this.initPlugins(CanvasRenderer.__plugins); - - sayHello('Canvas'); - - this.resize(this.options.width, this.options.height); - } - - /** - * Adds a new system to the renderer. It does nothing in the CanvasRenderer. - */ - addSystem(): this - { - return this; - } - - /** - * Renders the object to its WebGL view. - * - * @param displayObject - The object to be rendered. - * @param options - Object to use for render options. - * @param {PIXI.RenderTexture} [options.renderTexture] - The render texture to render to. - * @param {boolean} [options.clear=true] - Should the canvas be cleared before the new render. - * @param {PIXI.Matrix} [options.transform] - A transform to apply to the render texture before rendering. - * @param {boolean} [options.skipUpdateTransform=false] - Should we skip the update transform pass? - */ - render(displayObject: DisplayObject, options?: IRendererRenderOptions): void; - - /** - * Please use the `option` render arguments instead. - * - * @deprecated Since 6.0.0 - * @param displayObject - The object to be rendered. - * @param renderTexture - The render texture to render to. - * @param clear - Should the canvas be cleared before the new render. - * @param transform - A transform to apply to the render texture before rendering. - * @param skipUpdateTransform - Should we skip the update transform pass? - */ - render(displayObject: DisplayObject, renderTexture?: RenderTexture | BaseRenderTexture, - clear?: boolean, transform?: Matrix, skipUpdateTransform?: boolean): void; - - /** @ignore */ - public render(displayObject: DisplayObject, options?: IRendererRenderOptions | RenderTexture | BaseRenderTexture): void - { - if (!this.view) - { - return; - } - - let renderTexture: BaseRenderTexture | RenderTexture; - let clear: boolean; - let transform: Matrix; - let skipUpdateTransform: boolean; - - if (options) - { - if (options instanceof RenderTexture || options instanceof BaseRenderTexture) - { - // #if _DEBUG - deprecation('6.0.0', 'CanvasRenderer#render arguments changed, use options instead.'); - // #endif - - /* eslint-disable prefer-rest-params */ - renderTexture = options; - clear = arguments[2]; - transform = arguments[3]; - skipUpdateTransform = arguments[4]; - /* eslint-enable prefer-rest-params */ - } - else - { - renderTexture = options.renderTexture; - clear = options.clear; - transform = options.transform; - skipUpdateTransform = options.skipUpdateTransform; - } - } - - // can be handy to know! - this.renderingToScreen = !renderTexture; - - this.emit('prerender'); - - const rootResolution = this.resolution; - - if (renderTexture) - { - renderTexture = renderTexture.castToBaseTexture() as BaseRenderTexture; - - if (!renderTexture._canvasRenderTarget) - { - renderTexture._canvasRenderTarget = new CanvasRenderTarget( - renderTexture.width, - renderTexture.height, - renderTexture.resolution - ); - renderTexture.resource = new CanvasResource(renderTexture._canvasRenderTarget.canvas); - renderTexture.valid = true; - } - - this.context = renderTexture._canvasRenderTarget.context as CrossPlatformCanvasRenderingContext2D; - this.resolution = renderTexture._canvasRenderTarget.resolution; - } - else - { - this.context = this.rootContext; - } - - const context = this.context; - - this._projTransform = transform || null; - - if (!renderTexture) - { - this._lastObjectRendered = displayObject; - } - - if (!skipUpdateTransform) - { - // update the scene graph - const cacheParent = displayObject.enableTempParent(); - - displayObject.updateTransform(); - displayObject.disableTempParent(cacheParent); - } - - context.save(); - context.setTransform(1, 0, 0, 1, 0, 0); - context.globalAlpha = 1; - this._activeBlendMode = BLEND_MODES.NORMAL; - this._outerBlend = false; - context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; - - if (clear !== undefined ? clear : this.clearBeforeRender) - { - if (this.renderingToScreen) - { - context.clearRect(0, 0, this.width, this.height); - - if (this.backgroundAlpha > 0) - { - context.globalAlpha = this.useContextAlpha ? this.backgroundAlpha : 1; - context.fillStyle = this._backgroundColorString; - context.fillRect(0, 0, this.width, this.height); - context.globalAlpha = 1; - } - } - else - { - renderTexture = (renderTexture as BaseRenderTexture); - renderTexture._canvasRenderTarget.clear(); - - const clearColor = renderTexture.clearColor; - - if (clearColor[3] > 0) - { - context.globalAlpha = this.useContextAlpha ? clearColor[3] : 1; - context.fillStyle = hex2string(rgb2hex(clearColor)); - context.fillRect(0, 0, renderTexture.realWidth, renderTexture.realHeight); - context.globalAlpha = 1; - } - } - } - - // TODO RENDER TARGET STUFF HERE.. - const tempContext = this.context; - - this.context = context; - displayObject.renderCanvas(this); - this.context = tempContext; - - context.restore(); - - this.resolution = rootResolution; - this._projTransform = null; - - this.emit('postrender'); - } - - /** - * Sets matrix of context. - * called only from render() methods - * takes care about resolution - * @param transform - world matrix of current element - * @param roundPixels - whether to round (tx,ty) coords - * @param localResolution - If specified, used instead of `renderer.resolution` for local scaling - */ - setContextTransform(transform: Matrix, roundPixels?: boolean, localResolution?: number): void - { - let mat = transform; - const proj = this._projTransform; - const resolution = this.resolution; - - localResolution = localResolution || resolution; - - if (proj) - { - mat = tempMatrix; - mat.copyFrom(transform); - mat.prepend(proj); - } - - if (roundPixels) - { - this.context.setTransform( - mat.a * localResolution, - mat.b * localResolution, - mat.c * localResolution, - mat.d * localResolution, - (mat.tx * resolution) | 0, - (mat.ty * resolution) | 0 - ); - } - else - { - this.context.setTransform( - mat.a * localResolution, - mat.b * localResolution, - mat.c * localResolution, - mat.d * localResolution, - mat.tx * resolution, - mat.ty * resolution - ); - } - } - - /** - * Clear the canvas of renderer. - * - * @param {string} [clearColor] - Clear the canvas with this color, except the canvas is transparent. - * @param {number} [alpha] - Alpha to apply to the background fill color. - */ - public clear(clearColor: string = this._backgroundColorString, alpha: number = this.backgroundAlpha): void - { - const { context } = this; - - context.clearRect(0, 0, this.width, this.height); - - if (clearColor) - { - context.globalAlpha = this.useContextAlpha ? alpha : 1; - context.fillStyle = clearColor; - context.fillRect(0, 0, this.width, this.height); - context.globalAlpha = 1; - } - } - - /** - * Sets the blend mode of the renderer. - * - * @param {number} blendMode - See {@link PIXI.BLEND_MODES} for valid values. - * @param {boolean} [readyForOuterBlend=false] - Some blendModes are dangerous, they affect outer space of sprite. - * Pass `true` only if you are ready to use them. - */ - setBlendMode(blendMode: BLEND_MODES, readyForOuterBlend?: boolean): void - { - const outerBlend = blendMode === BLEND_MODES.SRC_IN - || blendMode === BLEND_MODES.SRC_OUT - || blendMode === BLEND_MODES.DST_IN - || blendMode === BLEND_MODES.DST_ATOP; - - if (!readyForOuterBlend && outerBlend) - { - blendMode = BLEND_MODES.NORMAL; - } - - if (this._activeBlendMode === blendMode) - { - return; - } - - this._activeBlendMode = blendMode; - this._outerBlend = outerBlend; - this.context.globalCompositeOperation = this.blendModes[blendMode]; - } - - /** - * Removes everything from the renderer and optionally removes the Canvas DOM element. - * - * @param {boolean} [removeView=false] - Removes the Canvas element from the DOM. - */ - public destroy(removeView?: boolean): void - { - // call the base destroy - super.destroy(removeView); - - this.context = null; - - this.refresh = true; - - this.maskManager.destroy(); - this.maskManager = null; - - this.smoothProperty = null; - } - - /** - * Resizes the canvas view to the specified width and height. - * - * @extends PIXI.AbstractRenderer#resize - * - * @param desiredScreenWidth - the desired width of the screen - * @param desiredScreenHeight - the desired height of the screen - */ - public resize(desiredScreenWidth: number, desiredScreenHeight: number): void - { - super.resize(desiredScreenWidth, desiredScreenHeight); - - // reset the scale mode.. oddly this seems to be reset when the canvas is resized. - // surely a browser bug?? Let PixiJS fix that for you.. - if (this.smoothProperty) - { - this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); - } - } - - /** Checks if blend mode has changed. */ - invalidateBlendMode(): void - { - this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); - } - - static __plugins: IRendererPlugins; - - /** - * Collection of installed plugins. These are included by default in PIXI, but can be excluded - * by creating a custom build. Consult the README for more information about creating custom - * builds and excluding plugins. - * @member {object} plugins - * @readonly - * @property {PIXI.AccessibilityManager} accessibility Support tabbing interactive elements. - * @property {PIXI.CanvasExtract} extract Extract image data from renderer. - * @property {PIXI.InteractionManager} interaction Handles mouse, touch and pointer events. - * @property {PIXI.CanvasPrepare} prepare Pre-render display objects. - */ - - /** - * Adds a plugin to the renderer. - * - * @param pluginName - The name of the plugin. - * @param ctor - The constructor function or class for the plugin. - */ - static registerPlugin(pluginName: string, ctor: ICanvasRendererPluginConstructor): void - { - CanvasRenderer.__plugins = CanvasRenderer.__plugins || {}; - CanvasRenderer.__plugins[pluginName] = ctor; - } -} diff --git a/packages/canvas/canvas-renderer/src/Renderer.ts b/packages/canvas/canvas-renderer/src/Renderer.ts deleted file mode 100644 index 0b08d2467e0..00000000000 --- a/packages/canvas/canvas-renderer/src/Renderer.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Renderer } from '@pixi/core'; -import { CanvasRenderer } from './CanvasRenderer'; - -import type { AbstractRenderer, IRendererOptionsAuto } from '@pixi/core'; - -// Reference to Renderer.create static function -const parentCreate = Renderer.create; - -/** - * Override the Renderer.create to fallback to use CanvasRenderer. - * Also supports forceCanvas option with Application or autoDetectRenderer. - * @private - */ -Renderer.create = function create(options: IRendererOptionsAuto): AbstractRenderer -{ - const forceCanvas = options && options.forceCanvas; - - if (!forceCanvas) - { - try - { - return parentCreate(options); - } - catch (err) - { - // swallow WebGL-unsupported error - } - } - - return new CanvasRenderer(options); -}; diff --git a/packages/canvas/canvas-sprite-tiling/global.d.ts b/packages/canvas/canvas-sprite-tiling/global.d.ts deleted file mode 100644 index e445fb00272..00000000000 --- a/packages/canvas/canvas-sprite-tiling/global.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare namespace GlobalMixins { - interface TilingSprite { - _canvasPattern: CanvasPattern; - } -} diff --git a/packages/canvas/canvas-sprite/README.md b/packages/canvas/canvas-sprite/README.md deleted file mode 100644 index 70029da896f..00000000000 --- a/packages/canvas/canvas-sprite/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/canvas-sprite - -## Installation - -```bash -npm install @pixi/canvas-sprite -``` - -## Usage - -```js -import { CanvasSpriteRenderer } from '@pixi/canvas-sprite'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; - -CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer); -``` \ No newline at end of file diff --git a/packages/canvas/canvas-sprite/global.d.ts b/packages/canvas/canvas-sprite/global.d.ts deleted file mode 100644 index 5f57e9e5974..00000000000 --- a/packages/canvas/canvas-sprite/global.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare namespace GlobalMixins { - interface Sprite { - _tintedCanvas: HTMLCanvasElement|HTMLImageElement; - _renderCanvas(renderer: import('@pixi/canvas-renderer').CanvasRenderer): void; - } -} diff --git a/packages/canvas/canvas-sprite/test/CanvasSpriteRenderer.tests.ts b/packages/canvas/canvas-sprite/test/CanvasSpriteRenderer.tests.ts deleted file mode 100644 index 924dff80880..00000000000 --- a/packages/canvas/canvas-sprite/test/CanvasSpriteRenderer.tests.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Texture } from '@pixi/core'; -import { Sprite } from '@pixi/sprite'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { expect } from 'chai'; - -describe('CanvasSpriteRenderer', function () -{ - it('should still render a sprite after texture is destroyed', function () - { - const renderer = new CanvasRenderer({ width: 1, height: 1 }); - const texture = new Texture(Texture.WHITE); - const sprite = new Sprite(texture); - - renderer.render(sprite); - texture.destroy(); - - try - { - expect(() => { renderer.render(sprite); }).to.not.throw(); - } - finally - { - renderer.destroy(); - } - }); -}); diff --git a/packages/compressed-textures/README.md b/packages/compressed-textures/README.md index 55d48bc4833..e4dadda5d94 100644 --- a/packages/compressed-textures/README.md +++ b/packages/compressed-textures/README.md @@ -17,10 +17,5 @@ npm install @pixi/compressed-textures ## Usage ```js -import { CompressedTextureLoader, DDSLoader, KTXLoader } from '@pixi/compressed-textures'; -import { Loader } from '@pixi/loaders'; - -Loader.registerPlugin(CompressedTextureLoader); -Loader.registerPlugin(DDSLoader); -Loader.registerPlugin(KTXLoader); +import '@pixi/compressed-textures'; ``` diff --git a/packages/compressed-textures/global.d.ts b/packages/compressed-textures/global.d.ts new file mode 100644 index 00000000000..156f0dc1327 --- /dev/null +++ b/packages/compressed-textures/global.d.ts @@ -0,0 +1,8 @@ +declare namespace GlobalMixins +{ + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface BaseTexture + { + ktxKeyValueData: Map; + } +} diff --git a/packages/compressed-textures/package.json b/packages/compressed-textures/package.json index f1bf6a3fb99..5113f5fe9a0 100644 --- a/packages/compressed-textures/package.json +++ b/packages/compressed-textures/package.json @@ -1,6 +1,6 @@ { "name": "@pixi/compressed-textures", - "version": "6.3.0", + "version": "7.0.0-alpha", "description": "Loaders for compressed texture file formats", "keywords": [ "pixi.js", @@ -14,8 +14,20 @@ "homepage": "https://github.com/pixijs/pixi.js#readme", "license": "MIT", "main": "dist/cjs/compressed-textures.js", - "module": "dist/esm/compressed-textures.js", - "bundle": "dist/browser/compressed-textures.js", + "module": "dist/esm/compressed-textures.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/compressed-textures.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/compressed-textures.js" + } + } + }, "publishConfig": { "access": "public" }, @@ -34,10 +46,8 @@ "bugs": { "url": "https://github.com/pixijs/pixi.js/issues" }, - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/assets", + "@pixi/core" + ] } diff --git a/packages/compressed-textures/src/const.ts b/packages/compressed-textures/src/const.ts index abc8f655bbc..e1573724aa3 100644 --- a/packages/compressed-textures/src/const.ts +++ b/packages/compressed-textures/src/const.ts @@ -1,38 +1,39 @@ /** * WebGL internal formats, including compressed texture formats provided by extensions - * * @memberof PIXI * @static * @name INTERNAL_FORMATS * @enum {number} - * @property {number} COMPRESSED_RGB_S3TC_DXT1_EXT=0x83F0 - * @property {number} COMPRESSED_RGBA_S3TC_DXT1_EXT=0x83F1 - * @property {number} COMPRESSED_RGBA_S3TC_DXT3_EXT=0x83F2 - * @property {number} COMPRESSED_RGBA_S3TC_DXT5_EXT=0x83F3 - * @property {number} COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT=35917 - * @property {number} COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT=35918 - * @property {number} COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT=35919 - * @property {number} COMPRESSED_SRGB_S3TC_DXT1_EXT=35916 - * @property {number} COMPRESSED_R11_EAC=0x9270 - * @property {number} COMPRESSED_SIGNED_R11_EAC=0x9271 - * @property {number} COMPRESSED_RG11_EAC=0x9272 - * @property {number} COMPRESSED_SIGNED_RG11_EAC=0x9273 - * @property {number} COMPRESSED_RGB8_ETC2=0x9274 - * @property {number} COMPRESSED_RGBA8_ETC2_EAC=0x9278 - * @property {number} COMPRESSED_SRGB8_ETC2=0x9275 - * @property {number} COMPRESSED_SRGB8_ALPHA8_ETC2_EAC=0x9279 - * @property {number} COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2=0x9276 - * @property {number} COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2=0x9277 - * @property {number} COMPRESSED_RGB_PVRTC_4BPPV1_IMG=0x8C00 - * @property {number} COMPRESSED_RGBA_PVRTC_4BPPV1_IMG=0x8C02 - * @property {number} COMPRESSED_RGB_PVRTC_2BPPV1_IMG=0x8C01 - * @property {number} COMPRESSED_RGBA_PVRTC_2BPPV1_IMG=0x8C03 - * @property {number} COMPRESSED_RGB_ETC1_WEBGL=0x8D64 - * @property {number} COMPRESSED_RGB_ATC_WEBGL=0x8C92 - * @property {number} COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL=0x8C92 - * @property {number} COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL=0x87EE + * @property {number} [COMPRESSED_RGB_S3TC_DXT1_EXT=0x83F0] - + * @property {number} [COMPRESSED_RGBA_S3TC_DXT1_EXT=0x83F1] - + * @property {number} [COMPRESSED_RGBA_S3TC_DXT3_EXT=0x83F2] - + * @property {number} [COMPRESSED_RGBA_S3TC_DXT5_EXT=0x83F3] - + * @property {number} [COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT=35917] - + * @property {number} [COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT=35918] - + * @property {number} [COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT=35919] - + * @property {number} [COMPRESSED_SRGB_S3TC_DXT1_EXT=35916] - + * @property {number} [COMPRESSED_R11_EAC=0x9270] - + * @property {number} [COMPRESSED_SIGNED_R11_EAC=0x9271] - + * @property {number} [COMPRESSED_RG11_EAC=0x9272] - + * @property {number} [COMPRESSED_SIGNED_RG11_EAC=0x9273] - + * @property {number} [COMPRESSED_RGB8_ETC2=0x9274] - + * @property {number} [COMPRESSED_RGBA8_ETC2_EAC=0x9278] - + * @property {number} [COMPRESSED_SRGB8_ETC2=0x9275] - + * @property {number} [COMPRESSED_SRGB8_ALPHA8_ETC2_EAC=0x9279] - + * @property {number} [COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2=0x9276] - + * @property {number} [COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2=0x9277] - + * @property {number} [COMPRESSED_RGB_PVRTC_4BPPV1_IMG=0x8C00] - + * @property {number} [COMPRESSED_RGBA_PVRTC_4BPPV1_IMG=0x8C02] - + * @property {number} [COMPRESSED_RGB_PVRTC_2BPPV1_IMG=0x8C01] - + * @property {number} [COMPRESSED_RGBA_PVRTC_2BPPV1_IMG=0x8C03] - + * @property {number} [COMPRESSED_RGB_ETC1_WEBGL=0x8D64] - + * @property {number} [COMPRESSED_RGB_ATC_WEBGL=0x8C92] - + * @property {number} [COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL=0x8C92] - + * @property {number} [COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL=0x87EE] - */ -export enum INTERNAL_FORMATS { +export enum INTERNAL_FORMATS +// eslint-disable-next-line @typescript-eslint/indent +{ // WEBGL_compressed_texture_s3tc COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0, COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1, @@ -75,7 +76,6 @@ export enum INTERNAL_FORMATS { /** * Maps the compressed texture formats in {@link PIXI.INTERNAL_FORMATS} to the number of bytes taken by * each texel. - * * @memberof PIXI * @static * @ignore diff --git a/packages/compressed-textures/src/index.ts b/packages/compressed-textures/src/index.ts index a7268776fb2..ed9b174aa7c 100644 --- a/packages/compressed-textures/src/index.ts +++ b/packages/compressed-textures/src/index.ts @@ -1,3 +1,4 @@ export * from './const'; export * from './resources'; export * from './loaders'; +export * from './parsers'; diff --git a/packages/compressed-textures/src/loaders/CompressedTextureLoader.ts b/packages/compressed-textures/src/loaders/CompressedTextureLoader.ts deleted file mode 100644 index eb8f1dd088a..00000000000 --- a/packages/compressed-textures/src/loaders/CompressedTextureLoader.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { LoaderResource } from '@pixi/loaders'; -import { url } from '@pixi/utils'; - -import type { Loader } from '@pixi/loaders'; -import type { INTERNAL_FORMATS } from '../const'; - -/** - * Schema for compressed-texture manifests - * - * @ignore - * @see PIXI.CompressedTextureLoader - */ -export type CompressedTextureManifest = { - textures: Array<{ src: string, format?: keyof INTERNAL_FORMATS}>, - cacheID: string; -}; - -// Missing typings? - https://github.com/microsoft/TypeScript/issues/39655 -/** - * Compressed texture extensions - */ -/* eslint-disable camelcase */ -export type CompressedTextureExtensions = { - s3tc?: WEBGL_compressed_texture_s3tc, - s3tc_sRGB: WEBGL_compressed_texture_s3tc_srgb, - etc: any, - etc1: any, - pvrtc: any, - atc: any, - astc: WEBGL_compressed_texture_astc -}; -export type CompressedTextureExtensionRef = keyof CompressedTextureExtensions; -/* eslint-enable camelcase */ - -/** - * Loader plugin for handling compressed textures for all platforms. - * - * @class - * @memberof PIXI - * @implements PIXI.ILoaderPlugin - */ -export class CompressedTextureLoader -{ - /** Map of available texture extensions. */ - static textureExtensions: Partial; - - /** Map of available texture formats. */ - static textureFormats: { [P in keyof INTERNAL_FORMATS]?: number }; - - /** - * Called after a compressed-textures manifest is loaded. - * - * This will then load the correct compression format for the device. Your manifest should adhere - * to the following schema: - * - * ```js - * import { INTERNAL_FORMATS } from '@pixi/constants'; - * - * type CompressedTextureManifest = { - * textures: Array<{ src: string, format?: keyof INTERNAL_FORMATS}>, - * cacheID: string; - * }; - * ``` - * - * This is an example of a .json manifest file - * - * ```json - * { - * "cacheID":"asset", - * "textures":[ - * { "src":"asset.fallback.png" }, - * { "format":"COMPRESSED_RGBA_S3TC_DXT5_EXT", "src":"asset.s3tc.ktx" }, - * { "format":"COMPRESSED_RGBA8_ETC2_EAC", "src":"asset.etc.ktx" }, - * { "format":"RGBA_PVRTC_4BPPV1_IMG", "src":"asset.pvrtc.ktx" } - * ] - * } - * ``` - */ - static use(resource: LoaderResource, next: (...args: any[]) => void): void - { - const data: CompressedTextureManifest = resource.data; - const loader = this as unknown as Loader; - - if (resource.type === LoaderResource.TYPE.JSON - && data - && data.cacheID - && data.textures) - { - const textures = data.textures; - - let textureURL: string; - let fallbackURL: string; - - // Search for an extension that holds one the formats - for (let i = 0, j = textures.length; i < j; i++) - { - const texture = textures[i]; - const url = texture.src; - const format = texture.format; - - if (!format) - { - fallbackURL = url; - } - if (CompressedTextureLoader.textureFormats[format]) - { - textureURL = url; - break; - } - } - - textureURL = textureURL || fallbackURL; - - // Make sure we have a URL - if (!textureURL) - { - next(new Error(`Cannot load compressed-textures in ${resource.url}, make sure you provide a fallback`)); - - return; - } - if (textureURL === resource.url) - { - // Prevent infinite loops - next(new Error('URL of compressed texture cannot be the same as the manifest\'s URL')); - - return; - } - - const loadOptions = { - crossOrigin: resource.crossOrigin, - metadata: resource.metadata.imageMetadata, - parentResource: resource - }; - - const resourcePath = url.resolve(resource.url.replace(loader.baseUrl, ''), textureURL); - const resourceName = data.cacheID; - - // The appropriate loader should register the texture - loader.add(resourceName, resourcePath, loadOptions, (res: LoaderResource) => - { - if (res.error) - { - next(res.error); - - return; - } - - const { texture = null, textures = {} } = res; - - // Make sure texture/textures is assigned to parent resource - Object.assign(resource, { texture, textures }); - - // Pass along any error - next(); - }); - } - else - { - next(); - } - } - - /** - * Detects the available compressed texture extensions on the device. - * @ignore - */ - static add(): void - { - // Auto-detect WebGL compressed-texture extensions - const canvas = document.createElement('canvas'); - const gl = canvas.getContext('webgl'); - - if (!gl) - { - // #if _DEBUG - console.warn('WebGL not available for compressed textures. Silently failing.'); - // #endif - - return; - } - - const extensions = { - s3tc: gl.getExtension('WEBGL_compressed_texture_s3tc'), - s3tc_sRGB: gl.getExtension('WEBGL_compressed_texture_s3tc_srgb'), /* eslint-disable-line camelcase */ - etc: gl.getExtension('WEBGL_compressed_texture_etc'), - etc1: gl.getExtension('WEBGL_compressed_texture_etc1'), - pvrtc: gl.getExtension('WEBGL_compressed_texture_pvrtc') - || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc'), - atc: gl.getExtension('WEBGL_compressed_texture_atc'), - astc: gl.getExtension('WEBGL_compressed_texture_astc') - }; - - CompressedTextureLoader.textureExtensions = extensions; - CompressedTextureLoader.textureFormats = {}; - - // Assign all available compressed-texture formats - for (const extensionName in extensions) - { - const extension = extensions[extensionName as CompressedTextureExtensionRef]; - - if (!extension) - { - continue; - } - - Object.assign( - CompressedTextureLoader.textureFormats, - Object.getPrototypeOf(extension)); - } - } -} diff --git a/packages/compressed-textures/src/loaders/KTXLoader.ts b/packages/compressed-textures/src/loaders/KTXLoader.ts deleted file mode 100644 index 63f4ad9ef6c..00000000000 --- a/packages/compressed-textures/src/loaders/KTXLoader.ts +++ /dev/null @@ -1,411 +0,0 @@ -import { ALPHA_MODES, FORMATS, MIPMAP_MODES, TYPES } from '@pixi/constants'; -import { BaseTexture, BufferResource, Texture } from '@pixi/core'; -import { CompressedLevelBuffer, CompressedTextureResource } from '../resources/CompressedTextureResource'; -import { LoaderResource } from '@pixi/loaders'; -import { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const'; -import { registerCompressedTextures } from './registerCompressedTextures'; - -// Set KTX files to be loaded as an ArrayBuffer -LoaderResource.setExtensionXhrType('ktx', LoaderResource.XHR_RESPONSE_TYPE.BUFFER); - -/** - * The 12-byte KTX file identifier - * - * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.1 - * @ignore - */ -const FILE_IDENTIFIER = [0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A]; - -/** - * The value stored in the "endianness" field. - * - * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.2 - * @ignore - */ -const ENDIANNESS = 0x04030201; - -/** - * Byte offsets of the KTX file header fields - * - * @ignore - */ -const KTX_FIELDS = { - FILE_IDENTIFIER: 0, - ENDIANNESS: 12, - GL_TYPE: 16, - GL_TYPE_SIZE: 20, - GL_FORMAT: 24, - GL_INTERNAL_FORMAT: 28, - GL_BASE_INTERNAL_FORMAT: 32, - PIXEL_WIDTH: 36, - PIXEL_HEIGHT: 40, - PIXEL_DEPTH: 44, - NUMBER_OF_ARRAY_ELEMENTS: 48, - NUMBER_OF_FACES: 52, - NUMBER_OF_MIPMAP_LEVELS: 56, - BYTES_OF_KEY_VALUE_DATA: 60 -}; - -/** - * Byte size of the file header fields in {@code KTX_FIELDS} - * - * @ignore - */ -const FILE_HEADER_SIZE = 64; - -/** - * Maps {@link PIXI.TYPES} to the bytes taken per component, excluding those ones that are bit-fields. - * - * @ignore - */ -export const TYPES_TO_BYTES_PER_COMPONENT: { [id: number]: number } = { - [TYPES.UNSIGNED_BYTE]: 1, - [TYPES.UNSIGNED_SHORT]: 2, - [TYPES.INT]: 4, - [TYPES.UNSIGNED_INT]: 4, - [TYPES.FLOAT]: 4, - [TYPES.HALF_FLOAT]: 8 -}; - -/** - * Number of components in each {@link PIXI.FORMATS} - * - * @ignore - */ -export const FORMATS_TO_COMPONENTS: { [id: number]: number } = { - [FORMATS.RGBA]: 4, - [FORMATS.RGB]: 3, - [FORMATS.RG]: 2, - [FORMATS.RED]: 1, - [FORMATS.LUMINANCE]: 1, - [FORMATS.LUMINANCE_ALPHA]: 2, - [FORMATS.ALPHA]: 1 -}; - -/** - * Number of bytes per pixel in bit-field types in {@link PIXI.TYPES} - * - * @ignore - */ -export const TYPES_TO_BYTES_PER_PIXEL: { [id: number]: number } = { - [TYPES.UNSIGNED_SHORT_4_4_4_4]: 2, - [TYPES.UNSIGNED_SHORT_5_5_5_1]: 2, - [TYPES.UNSIGNED_SHORT_5_6_5]: 2 -}; - -/** - * Loader plugin for handling KTX texture container files. - * - * This KTX loader does not currently support the following features: - * * cube textures - * * 3D textures - * * vendor-specific key/value data parsing - * * endianness conversion for big-endian machines - * * embedded *.basis files - * - * It does supports the following features: - * * multiple textures per file - * * mipmapping (only for compressed formats) - * - * @class - * @memberof PIXI - * @implements PIXI.ILoaderPlugin - */ -export class KTXLoader -{ - /** - * Called after a KTX file is loaded. - * - * This will parse the KTX file header and add a {@code BaseTexture} to the texture - * cache. - * - * @see PIXI.Loader.loaderMiddleware - * @param resource - loader resource that is checked to see if it is a KTX file - * @param next - callback Function to call when done - */ - public static use(resource: LoaderResource, next: (...args: any[]) => void): void - { - if (resource.extension === 'ktx' && resource.data) - { - try - { - const url = resource.name || resource.url; - const { compressed, uncompressed } = KTXLoader.parse(url, resource.data); - - if (compressed) - { - Object.assign(resource, registerCompressedTextures( - url, - compressed, - resource.metadata, - )); - } - else if (uncompressed) - { - const textures: Record = {}; - - uncompressed.forEach((image, i) => - { - const texture = new Texture(new BaseTexture( - image.resource, - { - mipmap: MIPMAP_MODES.OFF, - alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, - type: image.type, - format: image.format, - } - )); - const cacheID = `${url}-${i + 1}`; - - BaseTexture.addToCache(texture.baseTexture, cacheID); - Texture.addToCache(texture, cacheID); - - if (i === 0) - { - textures[url] = texture; - BaseTexture.addToCache(texture.baseTexture, url); - Texture.addToCache(texture, url); - } - - textures[cacheID] = texture; - }); - - Object.assign(resource, { textures }); - } - } - catch (err) - { - next(err); - - return; - } - } - - next(); - } - - /** Parses the KTX file header, generates base-textures, and puts them into the texture cache. */ - private static parse(url: string, arrayBuffer: ArrayBuffer): { - compressed?: CompressedTextureResource[] - uncompressed?: { resource: BufferResource, type: TYPES, format: FORMATS }[] - } - { - const dataView = new DataView(arrayBuffer); - - if (!KTXLoader.validate(url, dataView)) - { - return null; - } - - const littleEndian = dataView.getUint32(KTX_FIELDS.ENDIANNESS, true) === ENDIANNESS; - const glType = dataView.getUint32(KTX_FIELDS.GL_TYPE, littleEndian); - // const glTypeSize = dataView.getUint32(KTX_FIELDS.GL_TYPE_SIZE, littleEndian); - const glFormat = dataView.getUint32(KTX_FIELDS.GL_FORMAT, littleEndian); - const glInternalFormat = dataView.getUint32(KTX_FIELDS.GL_INTERNAL_FORMAT, littleEndian); - const pixelWidth = dataView.getUint32(KTX_FIELDS.PIXEL_WIDTH, littleEndian); - const pixelHeight = dataView.getUint32(KTX_FIELDS.PIXEL_HEIGHT, littleEndian) || 1;// "pixelHeight = 0" -> "1" - const pixelDepth = dataView.getUint32(KTX_FIELDS.PIXEL_DEPTH, littleEndian) || 1;// ^^ - const numberOfArrayElements = dataView.getUint32(KTX_FIELDS.NUMBER_OF_ARRAY_ELEMENTS, littleEndian) || 1;// ^^ - const numberOfFaces = dataView.getUint32(KTX_FIELDS.NUMBER_OF_FACES, littleEndian); - const numberOfMipmapLevels = dataView.getUint32(KTX_FIELDS.NUMBER_OF_MIPMAP_LEVELS, littleEndian); - const bytesOfKeyValueData = dataView.getUint32(KTX_FIELDS.BYTES_OF_KEY_VALUE_DATA, littleEndian); - - // Whether the platform architecture is little endian. If littleEndian !== platformLittleEndian, then the - // file contents must be endian-converted! - // TODO: Endianness conversion - // const platformLittleEndian = new Uint8Array((new Uint32Array([ENDIANNESS])).buffer)[0] === 0x01; - - if (pixelHeight === 0 || pixelDepth !== 1) - { - throw new Error('Only 2D textures are supported'); - } - if (numberOfFaces !== 1) - { - throw new Error('CubeTextures are not supported by KTXLoader yet!'); - } - if (numberOfArrayElements !== 1) - { - // TODO: Support splitting array-textures into multiple BaseTextures - throw new Error('WebGL does not support array textures'); - } - - // TODO: 8x4 blocks for 2bpp pvrtc - const blockWidth = 4; - const blockHeight = 4; - - const alignedWidth = (pixelWidth + 3) & ~3; - const alignedHeight = (pixelHeight + 3) & ~3; - const imageBuffers = new Array(numberOfArrayElements); - let imagePixels = pixelWidth * pixelHeight; - - if (glType === 0) - { - // Align to 16 pixels (4x4 blocks) - imagePixels = alignedWidth * alignedHeight; - } - - let imagePixelByteSize: number; - - if (glType !== 0) - { - // Uncompressed texture format - if (TYPES_TO_BYTES_PER_COMPONENT[glType]) - { - imagePixelByteSize = TYPES_TO_BYTES_PER_COMPONENT[glType] * FORMATS_TO_COMPONENTS[glFormat]; - } - else - { - imagePixelByteSize = TYPES_TO_BYTES_PER_PIXEL[glType]; - } - } - else - { - imagePixelByteSize = INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[glInternalFormat]; - } - - if (imagePixelByteSize === undefined) - { - throw new Error('Unable to resolve the pixel format stored in the *.ktx file!'); - } - - const imageByteSize = imagePixels * imagePixelByteSize; - let mipByteSize = imageByteSize; - let mipWidth = pixelWidth; - let mipHeight = pixelHeight; - let alignedMipWidth = alignedWidth; - let alignedMipHeight = alignedHeight; - let imageOffset = FILE_HEADER_SIZE + bytesOfKeyValueData; - - for (let mipmapLevel = 0; mipmapLevel < numberOfMipmapLevels; mipmapLevel++) - { - const imageSize = dataView.getUint32(imageOffset, littleEndian); - let elementOffset = imageOffset + 4; - - for (let arrayElement = 0; arrayElement < numberOfArrayElements; arrayElement++) - { - // TODO: Maybe support 3D textures? :-) - // for (let zSlice = 0; zSlice < pixelDepth; zSlice) - - let mips = imageBuffers[arrayElement]; - - if (!mips) - { - mips = imageBuffers[arrayElement] = new Array(numberOfMipmapLevels); - } - - mips[mipmapLevel] = { - levelID: mipmapLevel, - - // don't align mipWidth when texture not compressed! (glType not zero) - levelWidth: numberOfMipmapLevels > 1 || glType !== 0 ? mipWidth : alignedMipWidth, - levelHeight: numberOfMipmapLevels > 1 || glType !== 0 ? mipHeight : alignedMipHeight, - levelBuffer: new Uint8Array(arrayBuffer, elementOffset, mipByteSize) - }; - elementOffset += mipByteSize; - } - - // HINT: Aligns to 4-byte boundary after jumping imageSize (in lieu of mipPadding) - imageOffset += imageSize + 4;// (+4 to jump the imageSize field itself) - imageOffset = imageOffset % 4 !== 0 ? imageOffset + 4 - (imageOffset % 4) : imageOffset; - - // Calculate mipWidth, mipHeight for _next_ iteration - mipWidth = (mipWidth >> 1) || 1; - mipHeight = (mipHeight >> 1) || 1; - alignedMipWidth = (mipWidth + blockWidth - 1) & ~(blockWidth - 1); - alignedMipHeight = (mipHeight + blockHeight - 1) & ~(blockHeight - 1); - - // Each mipmap level is 4-times smaller? - mipByteSize = alignedMipWidth * alignedMipHeight * imagePixelByteSize; - } - - // We use the levelBuffers feature of CompressedTextureResource b/c texture data is image-major, not level-major. - if (glType !== 0) - { - return { - uncompressed: imageBuffers.map((levelBuffers) => - { - let buffer: Float32Array | Uint32Array | Int32Array | Uint8Array = levelBuffers[0].levelBuffer; - let convertToInt = false; - - if (glType === TYPES.FLOAT) - { - buffer = new Float32Array( - levelBuffers[0].levelBuffer.buffer, - levelBuffers[0].levelBuffer.byteOffset, - levelBuffers[0].levelBuffer.byteLength / 4); - } - else if (glType === TYPES.UNSIGNED_INT) - { - convertToInt = true; - buffer = new Uint32Array( - levelBuffers[0].levelBuffer.buffer, - levelBuffers[0].levelBuffer.byteOffset, - levelBuffers[0].levelBuffer.byteLength / 4); - } - else if (glType === TYPES.INT) - { - convertToInt = true; - buffer = new Int32Array( - levelBuffers[0].levelBuffer.buffer, - levelBuffers[0].levelBuffer.byteOffset, - levelBuffers[0].levelBuffer.byteLength / 4); - } - - return { - resource: new BufferResource( - buffer, - { - width: levelBuffers[0].levelWidth, - height: levelBuffers[0].levelHeight, - } - ), - type: glType, - format: convertToInt ? KTXLoader.convertFormatToInteger(glFormat) : glFormat, - }; - }) - }; - } - - return { - compressed: imageBuffers.map((levelBuffers) => new CompressedTextureResource(null, { - format: glInternalFormat, - width: pixelWidth, - height: pixelHeight, - levels: numberOfMipmapLevels, - levelBuffers, - })) - }; - } - - /** Checks whether the arrayBuffer contains a valid *.ktx file. */ - private static validate(url: string, dataView: DataView): boolean - { - // NOTE: Do not optimize this into 3 32-bit integer comparison because the endianness - // of the data is not specified. - for (let i = 0; i < FILE_IDENTIFIER.length; i++) - { - if (dataView.getUint8(i) !== FILE_IDENTIFIER[i]) - { - // #if _DEBUG - console.error(`${url} is not a valid *.ktx file!`); - // #endif - - return false; - } - } - - return true; - } - - private static convertFormatToInteger(format: FORMATS) - { - switch (format) - { - case FORMATS.RGBA: return FORMATS.RGBA_INTEGER; - case FORMATS.RGB: return FORMATS.RGB_INTEGER; - case FORMATS.RG: return FORMATS.RG_INTEGER; - case FORMATS.RED: return FORMATS.RED_INTEGER; - default: return format; - } - } -} diff --git a/packages/compressed-textures/src/loaders/compressedTextureExtensions.ts b/packages/compressed-textures/src/loaders/compressedTextureExtensions.ts new file mode 100644 index 00000000000..b4e7507a906 --- /dev/null +++ b/packages/compressed-textures/src/loaders/compressedTextureExtensions.ts @@ -0,0 +1,14 @@ +// Missing typings? - https://github.com/microsoft/TypeScript/issues/39655 +/** Compressed texture extensions */ +/* eslint-disable camelcase */ +export type CompressedTextureExtensions = { + s3tc?: WEBGL_compressed_texture_s3tc, + s3tc_sRGB: WEBGL_compressed_texture_s3tc_srgb, + etc: any, + etc1: any, + pvrtc: any, + atc: any, + astc: WEBGL_compressed_texture_astc +}; +export type CompressedTextureExtensionRef = keyof CompressedTextureExtensions; +/* eslint-enable camelcase */ diff --git a/packages/compressed-textures/src/loaders/detectCompressedTextures.ts b/packages/compressed-textures/src/loaders/detectCompressedTextures.ts new file mode 100644 index 00000000000..f87b46415c5 --- /dev/null +++ b/packages/compressed-textures/src/loaders/detectCompressedTextures.ts @@ -0,0 +1,78 @@ +import type { FormatDetectionParser } from '@pixi/assets'; +import { settings, extensions as ext, ExtensionType } from '@pixi/core'; + +import type { CompressedTextureExtensionRef, CompressedTextureExtensions } from './compressedTextureExtensions'; + +let storedGl: WebGLRenderingContext; +let extensions: Partial; + +function getCompressedTextureExtensions() +{ + extensions = { + s3tc: storedGl.getExtension('WEBGL_compressed_texture_s3tc'), + s3tc_sRGB: storedGl.getExtension('WEBGL_compressed_texture_s3tc_srgb'), /* eslint-disable-line camelcase */ + etc: storedGl.getExtension('WEBGL_compressed_texture_etc'), + etc1: storedGl.getExtension('WEBGL_compressed_texture_etc1'), + pvrtc: storedGl.getExtension('WEBGL_compressed_texture_pvrtc') + || storedGl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc'), + atc: storedGl.getExtension('WEBGL_compressed_texture_atc'), + astc: storedGl.getExtension('WEBGL_compressed_texture_astc') + } as Partial; +} + +export const detectCompressedTextures = { + extension: { + type: ExtensionType.DetectionParser, + priority: 2, + }, + test: async (): Promise => + { + // Auto-detect WebGL compressed-texture extensions + const canvas = settings.ADAPTER.createCanvas(); + const gl = canvas.getContext('webgl'); + + if (!gl) + { + // #if _DEBUG + console.warn('WebGL not available for compressed textures.'); + // #endif + + return false; + } + + storedGl = gl; + + return true; + }, + add: async (formats: string[]): Promise => + { + if (!extensions) getCompressedTextureExtensions(); + + const textureFormats = []; + + // Assign all available compressed-texture formats + for (const extensionName in extensions) + { + const extension = extensions[extensionName as CompressedTextureExtensionRef]; + + if (!extension) + { + continue; + } + + textureFormats.push(extensionName); + } + + formats.unshift(...textureFormats); + + return formats; + }, + remove: async (formats: string[]): Promise => + { + if (!extensions) getCompressedTextureExtensions(); + + return formats.filter((f) => !(f in extensions)); + }, +} as FormatDetectionParser; + +ext.add(detectCompressedTextures); diff --git a/packages/compressed-textures/src/loaders/index.ts b/packages/compressed-textures/src/loaders/index.ts index b8b18afe38a..c0337736181 100644 --- a/packages/compressed-textures/src/loaders/index.ts +++ b/packages/compressed-textures/src/loaders/index.ts @@ -1,3 +1,5 @@ -export * from './CompressedTextureLoader'; -export * from './DDSLoader'; -export * from './KTXLoader'; +export * from './detectCompressedTextures'; +export * from './loadDDS'; +export * from './loadKTX'; +export * from './compressedTextureExtensions'; +export * from './resolveCompressedTextureUrl'; diff --git a/packages/compressed-textures/src/loaders/loadDDS.ts b/packages/compressed-textures/src/loaders/loadDDS.ts new file mode 100644 index 00000000000..dc6d9e0b1f4 --- /dev/null +++ b/packages/compressed-textures/src/loaders/loadDDS.ts @@ -0,0 +1,58 @@ +import { BaseTexture, extensions, ExtensionType, settings, utils, ALPHA_MODES, MIPMAP_MODES } from '@pixi/core'; +import { checkExtension, createTexture, LoaderParserPriority } from '@pixi/assets'; +import { parseDDS } from '../parsers'; + +import type { IBaseTextureOptions, Texture } from '@pixi/core'; +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; + +/** Load our DDS textures! */ +export const loadDDS: LoaderParser = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.High, + }, + + test(url: string): boolean + { + return checkExtension(url, '.dds'); + }, + + async load(url: string, asset: LoadAsset, loader: Loader): Promise + { + // get an array buffer... + const response = await settings.ADAPTER.fetch(url); + + const arrayBuffer = await response.arrayBuffer(); + + const resources = parseDDS(arrayBuffer); + + const textures = resources.map((resource) => + { + const base = new BaseTexture(resource, { + mipmap: MIPMAP_MODES.OFF, + alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, + resolution: utils.getResolutionOfUrl(url), + ...asset.data, + }); + + return createTexture(base, loader, url); + }); + + return textures.length === 1 ? textures[0] : textures; + }, + + unload(texture: Texture | Texture[]): void + { + if (Array.isArray(texture)) + { + texture.forEach((t) => t.destroy(true)); + } + else + { + texture.destroy(true); + } + } + +} as LoaderParser; + +extensions.add(loadDDS); diff --git a/packages/compressed-textures/src/loaders/loadKTX.ts b/packages/compressed-textures/src/loaders/loadKTX.ts new file mode 100644 index 00000000000..fe189b5bfc3 --- /dev/null +++ b/packages/compressed-textures/src/loaders/loadKTX.ts @@ -0,0 +1,72 @@ +import { ALPHA_MODES, MIPMAP_MODES, settings, utils, BaseTexture, extensions, ExtensionType } from '@pixi/core'; +import { checkExtension, createTexture, LoaderParserPriority } from '@pixi/assets'; +import { parseKTX } from '../parsers'; + +import type { IBaseTextureOptions, Texture } from '@pixi/core'; +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; + +/** Loads KTX textures! */ +export const loadKTX = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.High, + }, + + test(url: string): boolean + { + return checkExtension(url, '.ktx'); + }, + + async load(url: string, asset: LoadAsset, loader: Loader): Promise + { + // get an array buffer... + const response = await settings.ADAPTER.fetch(url); + + const arrayBuffer = await response.arrayBuffer(); + + const { compressed, uncompressed, kvData } = parseKTX(url, arrayBuffer); + + const resources = compressed ?? uncompressed; + + const options = { + mipmap: MIPMAP_MODES.OFF, + alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA, + resolution: utils.getResolutionOfUrl(url), + ...asset.data, + }; + + const textures = resources.map((resource) => + { + if (resources === uncompressed) + { + Object.assign(options, { + type: (resource as typeof uncompressed[0]).type, + format: (resource as typeof uncompressed[0]).format, + }); + } + + const base = new BaseTexture(resource, options); + + base.ktxKeyValueData = kvData; + + return createTexture(base, loader, url); + }); + + return textures.length === 1 ? textures[0] : textures; + }, + + unload(texture: Texture | Texture[]): void + { + if (Array.isArray(texture)) + { + texture.forEach((t) => t.destroy(true)); + } + else + { + texture.destroy(true); + } + } + +} as LoaderParser; + +extensions.add(loadKTX); diff --git a/packages/compressed-textures/src/loaders/registerCompressedTextures.ts b/packages/compressed-textures/src/loaders/registerCompressedTextures.ts deleted file mode 100644 index 6930b41e681..00000000000 --- a/packages/compressed-textures/src/loaders/registerCompressedTextures.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { MIPMAP_MODES, ALPHA_MODES } from '@pixi/constants'; -import { BaseTexture, Texture } from '@pixi/core'; - -import type { LoaderResource, IResourceMetadata } from '@pixi/loaders'; -import type { CompressedTextureResource } from '../resources/CompressedTextureResource'; - -/** - * Result when calling registerCompressedTextures. - * @ignore - */ -type CompressedTexturesResult = Pick; - -/** - * Creates base-textures and textures for each compressed-texture resource and adds them into the global - * texture cache. The first texture has two IDs - `${url}`, `${url}-1`; while the rest have an ID of the - * form `${url}-i`. - * - * @param url - the original address of the resources - * @param resources - the resources backing texture data - * @ignore - */ -export function registerCompressedTextures(url: string, - resources: CompressedTextureResource[], - metadata: IResourceMetadata): CompressedTexturesResult -{ - const result: CompressedTexturesResult = { - textures: {}, - texture: null, - }; - - if (!resources) - { - return result; - } - - const textures = resources.map((resource) => - ( - new Texture(new BaseTexture(resource, Object.assign({ - mipmap: MIPMAP_MODES.OFF, - alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA - }, metadata))) - )); - - textures.forEach((texture, i) => - { - const { baseTexture } = texture; - const cacheID = `${url}-${i + 1}`; - - BaseTexture.addToCache(baseTexture, cacheID); - Texture.addToCache(texture, cacheID); - - if (i === 0) - { - BaseTexture.addToCache(baseTexture, url); - Texture.addToCache(texture, url); - result.texture = texture; - } - - result.textures[cacheID] = texture; - }); - - return result; -} diff --git a/packages/compressed-textures/src/loaders/resolveCompressedTextureUrl.ts b/packages/compressed-textures/src/loaders/resolveCompressedTextureUrl.ts new file mode 100644 index 00000000000..667a9c292f7 --- /dev/null +++ b/packages/compressed-textures/src/loaders/resolveCompressedTextureUrl.ts @@ -0,0 +1,50 @@ +import { settings, extensions, ExtensionType } from '@pixi/core'; + +import type { ResolveAsset, ResolveURLParser } from '@pixi/assets'; + +export const resolveCompressedTextureUrl = { + extension: ExtensionType.ResolveParser, + test: (value: string) => + { + const temp = value.split('?')[0]; + const extension = temp.split('.').pop(); + + return ['basis', 'ktx', 'dds'].includes(extension); + }, + parse: (value: string): ResolveAsset => + { + const temp = value.split('?')[0]; + const extension = temp.split('.').pop(); + + if (extension === 'ktx') + { + const extensions = [ + '.s3tc.ktx', + '.s3tc_sRGB.ktx', + '.etc.ktx', + '.etc1.ktx', + '.pvrt.ktx', + '.atc.ktx', + '.astc.ktx' + ]; + + // check if value ends with one of the extensions + if (extensions.some((ext) => value.endsWith(ext))) + { + return { + resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + format: extensions.find((ext) => value.endsWith(ext)), + src: value, + }; + } + } + + return { + resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + format: value.split('.').pop(), + src: value, + }; + }, +} as ResolveURLParser; + +extensions.add(resolveCompressedTextureUrl); diff --git a/packages/compressed-textures/src/parsers/index.ts b/packages/compressed-textures/src/parsers/index.ts new file mode 100644 index 00000000000..64586560a39 --- /dev/null +++ b/packages/compressed-textures/src/parsers/index.ts @@ -0,0 +1,3 @@ +export * from './parseDDS'; +export * from './parseKTX'; + diff --git a/packages/compressed-textures/src/loaders/DDSLoader.ts b/packages/compressed-textures/src/parsers/parseDDS.ts similarity index 51% rename from packages/compressed-textures/src/loaders/DDSLoader.ts rename to packages/compressed-textures/src/parsers/parseDDS.ts index 05686bb7982..36dab547f9d 100644 --- a/packages/compressed-textures/src/loaders/DDSLoader.ts +++ b/packages/compressed-textures/src/parsers/parseDDS.ts @@ -1,10 +1,5 @@ import { CompressedTextureResource } from '../resources'; import { INTERNAL_FORMATS, INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const'; -import { LoaderResource } from '@pixi/loaders'; -import { registerCompressedTextures } from './registerCompressedTextures'; - -// Set DDS files to be loaded as an ArrayBuffer -LoaderResource.setExtensionXhrType('dds', LoaderResource.XHR_RESPONSE_TYPE.BUFFER); const DDS_MAGIC_SIZE = 4; const DDS_HEADER_SIZE = 124; @@ -16,7 +11,6 @@ const DDS_MAGIC = 0x20534444; /** * DWORD offsets of the DDS file header fields (relative to file start). - * * @ignore */ const DDS_FIELDS = { @@ -30,7 +24,6 @@ const DDS_FIELDS = { /** * DWORD offsets of the DDS PIXEL_FORMAT fields. - * * @ignore */ const DDS_PF_FIELDS = { @@ -46,7 +39,6 @@ const DDS_PF_FIELDS = { /** * DWORD offsets of the DDS_HEADER_DX10 fields. - * * @ignore */ const DDS_DX10_FIELDS = { @@ -59,11 +51,12 @@ const DDS_DX10_FIELDS = { /** * @see https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format + * This is way over-blown for us! Lend us a hand, and remove the ones that aren't used (but set the remaining + * ones to their correct value) * @ignore */ -// This is way over-blown for us! Lend us a hand, and remove the ones that aren't used (but set the remaining -// ones to their correct value) -enum DXGI_FORMAT { +enum DXGI_FORMAT + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R32G32B32A32_TYPELESS, DXGI_FORMAT_R32G32B32A32_FLOAT, @@ -190,10 +183,10 @@ enum DXGI_FORMAT { /** * Possible values of the field {@link DDS_DX10_FIELDS.RESOURCE_DIMENSION} - * * @ignore */ -enum D3D10_RESOURCE_DIMENSION { +enum D3D10_RESOURCE_DIMENSION + { DDS_DIMENSION_TEXTURE1D = 2, DDS_DIMENSION_TEXTURE2D = 3, DDS_DIMENSION_TEXTURE3D = 6 @@ -219,7 +212,6 @@ const DDS_RESOURCE_MISC_TEXTURECUBE = 0x4; /** * Maps `FOURCC_*` formats to internal formats (see {@link PIXI.INTERNAL_FORMATS}). - * * @ignore */ const FOURCC_TO_FORMAT: { [id: number]: number } = { @@ -230,7 +222,6 @@ const FOURCC_TO_FORMAT: { [id: number]: number } = { /** * Maps {@link DXGI_FORMAT} to types/internal-formats (see {@link PIXI.TYPES}, {@link PIXI.INTERNAL_FORMATS}) - * * @ignore */ const DXGI_TO_FORMAT: { [id: number]: number } = { @@ -249,191 +240,159 @@ const DXGI_TO_FORMAT: { [id: number]: number } = { }; /** - * @class - * @memberof PIXI - * @implements PIXI.ILoaderPlugin + * Parses the DDS file header, generates base-textures, and puts them into the texture cache. * @see https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide + * @param arrayBuffer + * @memberof PIXI */ -export class DDSLoader +export function parseDDS(arrayBuffer: ArrayBuffer): CompressedTextureResource[] { - /** - * Registers a DDS compressed texture - * @see PIXI.Loader.loaderMiddleware - * @param resource - loader resource that is checked to see if it is a DDS file - * @param next - callback Function to call when done - */ - public static use(resource: LoaderResource, next: (...args: any[]) => void): void - { - if (resource.extension === 'dds' && resource.data) - { - try - { - Object.assign(resource, registerCompressedTextures( - resource.name || resource.url, - DDSLoader.parse(resource.data), - resource.metadata, - )); - } - catch (err) - { - next(err); + const data = new Uint32Array(arrayBuffer); + const magicWord = data[0]; - return; - } - } - - next(); - } - - /** Parses the DDS file header, generates base-textures, and puts them into the texture cache. */ - private static parse(arrayBuffer: ArrayBuffer): CompressedTextureResource[] + if (magicWord !== DDS_MAGIC) { - const data = new Uint32Array(arrayBuffer); - const magicWord = data[0]; + throw new Error('Invalid DDS file magic word'); + } - if (magicWord !== DDS_MAGIC) - { - throw new Error('Invalid DDS file magic word'); - } + const header = new Uint32Array(arrayBuffer, 0, DDS_HEADER_SIZE / Uint32Array.BYTES_PER_ELEMENT); - const header = new Uint32Array(arrayBuffer, 0, DDS_HEADER_SIZE / Uint32Array.BYTES_PER_ELEMENT); + // DDS header fields + const height = header[DDS_FIELDS.HEIGHT]; + const width = header[DDS_FIELDS.WIDTH]; + const mipmapCount = header[DDS_FIELDS.MIPMAP_COUNT]; - // DDS header fields - const height = header[DDS_FIELDS.HEIGHT]; - const width = header[DDS_FIELDS.WIDTH]; - const mipmapCount = header[DDS_FIELDS.MIPMAP_COUNT]; + // PIXEL_FORMAT fields + const pixelFormat = new Uint32Array( + arrayBuffer, + DDS_FIELDS.PIXEL_FORMAT * Uint32Array.BYTES_PER_ELEMENT, + DDS_HEADER_PF_SIZE / Uint32Array.BYTES_PER_ELEMENT); + const formatFlags = pixelFormat[PF_FLAGS]; - // PIXEL_FORMAT fields - const pixelFormat = new Uint32Array( - arrayBuffer, - DDS_FIELDS.PIXEL_FORMAT * Uint32Array.BYTES_PER_ELEMENT, - DDS_HEADER_PF_SIZE / Uint32Array.BYTES_PER_ELEMENT); - const formatFlags = pixelFormat[PF_FLAGS]; + // File contains compressed texture(s) + if (formatFlags & DDPF_FOURCC) + { + const fourCC = pixelFormat[DDS_PF_FIELDS.FOURCC]; - // File contains compressed texture(s) - if (formatFlags & DDPF_FOURCC) + // File contains one DXTn compressed texture + if (fourCC !== FOURCC_DX10) { - const fourCC = pixelFormat[DDS_PF_FIELDS.FOURCC]; - - // File contains one DXTn compressed texture - if (fourCC !== FOURCC_DX10) - { - const internalFormat = FOURCC_TO_FORMAT[fourCC]; + const internalFormat = FOURCC_TO_FORMAT[fourCC]; - const dataOffset = DDS_MAGIC_SIZE + DDS_HEADER_SIZE; - const texData = new Uint8Array(arrayBuffer, dataOffset); + const dataOffset = DDS_MAGIC_SIZE + DDS_HEADER_SIZE; + const texData = new Uint8Array(arrayBuffer, dataOffset); - const resource = new CompressedTextureResource(texData, { - format: internalFormat, - width, - height, - levels: mipmapCount // CompressedTextureResource will separate the levelBuffers for us! - }); + const resource = new CompressedTextureResource(texData, { + format: internalFormat, + width, + height, + levels: mipmapCount // CompressedTextureResource will separate the levelBuffers for us! + }); - return [resource]; - } + return [resource]; + } - // FOURCC_DX10 indicates there is a 20-byte DDS_HEADER_DX10 after DDS_HEADER - const dx10Offset = DDS_MAGIC_SIZE + DDS_HEADER_SIZE; - const dx10Header = new Uint32Array( - data.buffer, - dx10Offset, - DDS_HEADER_DX10_SIZE / Uint32Array.BYTES_PER_ELEMENT); - const dxgiFormat = dx10Header[DDS_DX10_FIELDS.DXGI_FORMAT]; - const resourceDimension = dx10Header[DDS_DX10_FIELDS.RESOURCE_DIMENSION]; - const miscFlag = dx10Header[DDS_DX10_FIELDS.MISC_FLAG]; - const arraySize = dx10Header[DDS_DX10_FIELDS.ARRAY_SIZE]; - - // Map dxgiFormat to PIXI.INTERNAL_FORMATS - const internalFormat = DXGI_TO_FORMAT[dxgiFormat]; - - if (internalFormat === undefined) - { - throw new Error(`DDSLoader cannot parse texture data with DXGI format ${dxgiFormat}`); - } - if (miscFlag === DDS_RESOURCE_MISC_TEXTURECUBE) - { - // FIXME: Anybody excited about cubemap compressed textures? - throw new Error('DDSLoader does not support cubemap textures'); - } - if (resourceDimension === D3D10_RESOURCE_DIMENSION.DDS_DIMENSION_TEXTURE3D) - { - // FIXME: Anybody excited about 3D compressed textures? - throw new Error('DDSLoader does not supported 3D texture data'); - } + // FOURCC_DX10 indicates there is a 20-byte DDS_HEADER_DX10 after DDS_HEADER + const dx10Offset = DDS_MAGIC_SIZE + DDS_HEADER_SIZE; + const dx10Header = new Uint32Array( + data.buffer, + dx10Offset, + DDS_HEADER_DX10_SIZE / Uint32Array.BYTES_PER_ELEMENT); + const dxgiFormat = dx10Header[DDS_DX10_FIELDS.DXGI_FORMAT]; + const resourceDimension = dx10Header[DDS_DX10_FIELDS.RESOURCE_DIMENSION]; + const miscFlag = dx10Header[DDS_DX10_FIELDS.MISC_FLAG]; + const arraySize = dx10Header[DDS_DX10_FIELDS.ARRAY_SIZE]; + + // Map dxgiFormat to PIXI.INTERNAL_FORMATS + const internalFormat = DXGI_TO_FORMAT[dxgiFormat]; + + if (internalFormat === undefined) + { + throw new Error(`DDSParser cannot parse texture data with DXGI format ${dxgiFormat}`); + } + if (miscFlag === DDS_RESOURCE_MISC_TEXTURECUBE) + { + // FIXME: Anybody excited about cubemap compressed textures? + throw new Error('DDSParser does not support cubemap textures'); + } + if (resourceDimension === D3D10_RESOURCE_DIMENSION.DDS_DIMENSION_TEXTURE3D) + { + // FIXME: Anybody excited about 3D compressed textures? + throw new Error('DDSParser does not supported 3D texture data'); + } - // Uint8Array buffers of image data, including all mipmap levels in each image - const imageBuffers = new Array(); - const dataOffset = DDS_MAGIC_SIZE + // Uint8Array buffers of image data, including all mipmap levels in each image + const imageBuffers = new Array(); + const dataOffset = DDS_MAGIC_SIZE + DDS_HEADER_SIZE + DDS_HEADER_DX10_SIZE; - if (arraySize === 1) - { - // No need bothering with the imageSize calculation! - imageBuffers.push(new Uint8Array(arrayBuffer, dataOffset)); - } - else - { - // Calculate imageSize for each texture, and then locate each image's texture data + if (arraySize === 1) + { + // No need bothering with the imageSize calculation! + imageBuffers.push(new Uint8Array(arrayBuffer, dataOffset)); + } + else + { + // Calculate imageSize for each texture, and then locate each image's texture data - const pixelSize = INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[internalFormat]; - let imageSize = 0; - let levelWidth = width; - let levelHeight = height; + const pixelSize = INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[internalFormat]; + let imageSize = 0; + let levelWidth = width; + let levelHeight = height; - for (let i = 0; i < mipmapCount; i++) - { - const alignedLevelWidth = Math.max(1, (levelWidth + 3) & ~3); - const alignedLevelHeight = Math.max(1, (levelHeight + 3) & ~3); + for (let i = 0; i < mipmapCount; i++) + { + const alignedLevelWidth = Math.max(1, (levelWidth + 3) & ~3); + const alignedLevelHeight = Math.max(1, (levelHeight + 3) & ~3); - const levelSize = alignedLevelWidth * alignedLevelHeight * pixelSize; + const levelSize = alignedLevelWidth * alignedLevelHeight * pixelSize; - imageSize += levelSize; + imageSize += levelSize; - levelWidth = levelWidth >>> 1; - levelHeight = levelHeight >>> 1; - } + levelWidth = levelWidth >>> 1; + levelHeight = levelHeight >>> 1; + } - let imageOffset = dataOffset; + let imageOffset = dataOffset; - // NOTE: Cubemaps have 6-images per texture (but they aren't supported so ^_^) - for (let i = 0; i < arraySize; i++) - { - imageBuffers.push(new Uint8Array(arrayBuffer, imageOffset, imageSize)); - imageOffset += imageSize; - } + // NOTE: Cubemaps have 6-images per texture (but they aren't supported so ^_^) + for (let i = 0; i < arraySize; i++) + { + imageBuffers.push(new Uint8Array(arrayBuffer, imageOffset, imageSize)); + imageOffset += imageSize; } - - // Uint8Array -> CompressedTextureResource, and we're done! - return imageBuffers.map((buffer) => new CompressedTextureResource(buffer, { - format: internalFormat, - width, - height, - levels: mipmapCount - })); - } - if (formatFlags & DDPF_RGB) - { - // FIXME: We might want to allow uncompressed *.dds files? - throw new Error('DDSLoader does not support uncompressed texture data.'); - } - if (formatFlags & DDPF_YUV) - { - // FIXME: Does anybody need this feature? - throw new Error('DDSLoader does not supported YUV uncompressed texture data.'); - } - if (formatFlags & DDPF_LUMINANCE) - { - // FIXME: Microsoft says older DDS filers use this feature! Probably not worth the effort! - throw new Error('DDSLoader does not support single-channel (lumninance) texture data!'); - } - if (formatFlags & DDPF_ALPHA) - { - // FIXME: I'm tired! See above =) - throw new Error('DDSLoader does not support single-channel (alpha) texture data!'); } - throw new Error('DDSLoader failed to load a texture file due to an unknown reason!'); + // Uint8Array -> CompressedTextureResource, and we're done! + return imageBuffers.map((buffer) => new CompressedTextureResource(buffer, { + format: internalFormat, + width, + height, + levels: mipmapCount + })); + } + if (formatFlags & DDPF_RGB) + { + // FIXME: We might want to allow uncompressed *.dds files? + throw new Error('DDSParser does not support uncompressed texture data.'); } + if (formatFlags & DDPF_YUV) + { + // FIXME: Does anybody need this feature? + throw new Error('DDSParser does not supported YUV uncompressed texture data.'); + } + if (formatFlags & DDPF_LUMINANCE) + { + // FIXME: Microsoft says older DDS filers use this feature! Probably not worth the effort! + throw new Error('DDSParser does not support single-channel (lumninance) texture data!'); + } + if (formatFlags & DDPF_ALPHA) + { + // FIXME: I'm tired! See above =) + throw new Error('DDSParser does not support single-channel (alpha) texture data!'); + } + + throw new Error('DDSParser failed to load a texture file due to an unknown reason!'); } + diff --git a/packages/compressed-textures/src/parsers/parseKTX.ts b/packages/compressed-textures/src/parsers/parseKTX.ts new file mode 100644 index 00000000000..c239de1dbb7 --- /dev/null +++ b/packages/compressed-textures/src/parsers/parseKTX.ts @@ -0,0 +1,373 @@ +import { BufferResource, FORMATS, TYPES } from '@pixi/core'; + +import { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const'; +import type { CompressedLevelBuffer } from '../resources'; +import { CompressedTextureResource } from '../resources'; + +/** + * The 12-byte KTX file identifier + * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.1 + * @ignore + */ +const FILE_IDENTIFIER = [0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A]; + +/** + * The value stored in the "endianness" field. + * @see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/#2.2 + * @ignore + */ +const ENDIANNESS = 0x04030201; + +/** + * Byte offsets of the KTX file header fields + * @ignore + */ +const KTX_FIELDS = { + FILE_IDENTIFIER: 0, + ENDIANNESS: 12, + GL_TYPE: 16, + GL_TYPE_SIZE: 20, + GL_FORMAT: 24, + GL_INTERNAL_FORMAT: 28, + GL_BASE_INTERNAL_FORMAT: 32, + PIXEL_WIDTH: 36, + PIXEL_HEIGHT: 40, + PIXEL_DEPTH: 44, + NUMBER_OF_ARRAY_ELEMENTS: 48, + NUMBER_OF_FACES: 52, + NUMBER_OF_MIPMAP_LEVELS: 56, + BYTES_OF_KEY_VALUE_DATA: 60 +}; + +/** + * Byte size of the file header fields in {@code KTX_FIELDS} + * @ignore + */ +const FILE_HEADER_SIZE = 64; + +/** + * Maps {@link PIXI.TYPES} to the bytes taken per component, excluding those ones that are bit-fields. + * @ignore + */ +export const TYPES_TO_BYTES_PER_COMPONENT: { [id: number]: number } = { + [TYPES.UNSIGNED_BYTE]: 1, + [TYPES.UNSIGNED_SHORT]: 2, + [TYPES.INT]: 4, + [TYPES.UNSIGNED_INT]: 4, + [TYPES.FLOAT]: 4, + [TYPES.HALF_FLOAT]: 8 +}; + +/** + * Number of components in each {@link PIXI.FORMATS} + * @ignore + */ +export const FORMATS_TO_COMPONENTS: { [id: number]: number } = { + [FORMATS.RGBA]: 4, + [FORMATS.RGB]: 3, + [FORMATS.RG]: 2, + [FORMATS.RED]: 1, + [FORMATS.LUMINANCE]: 1, + [FORMATS.LUMINANCE_ALPHA]: 2, + [FORMATS.ALPHA]: 1 +}; + +/** + * Number of bytes per pixel in bit-field types in {@link PIXI.TYPES} + * @ignore + */ +export const TYPES_TO_BYTES_PER_PIXEL: { [id: number]: number } = { + [TYPES.UNSIGNED_SHORT_4_4_4_4]: 2, + [TYPES.UNSIGNED_SHORT_5_5_5_1]: 2, + [TYPES.UNSIGNED_SHORT_5_6_5]: 2 +}; + +export function parseKTX(url: string, arrayBuffer: ArrayBuffer, loadKeyValueData = false): { + compressed?: CompressedTextureResource[] + uncompressed?: { resource: BufferResource, type: TYPES, format: FORMATS }[] + kvData: Map | null +} +{ + const dataView = new DataView(arrayBuffer); + + if (!validate(url, dataView)) + { + return null; + } + + const littleEndian = dataView.getUint32(KTX_FIELDS.ENDIANNESS, true) === ENDIANNESS; + const glType = dataView.getUint32(KTX_FIELDS.GL_TYPE, littleEndian); + // const glTypeSize = dataView.getUint32(KTX_FIELDS.GL_TYPE_SIZE, littleEndian); + const glFormat = dataView.getUint32(KTX_FIELDS.GL_FORMAT, littleEndian); + const glInternalFormat = dataView.getUint32(KTX_FIELDS.GL_INTERNAL_FORMAT, littleEndian); + const pixelWidth = dataView.getUint32(KTX_FIELDS.PIXEL_WIDTH, littleEndian); + const pixelHeight = dataView.getUint32(KTX_FIELDS.PIXEL_HEIGHT, littleEndian) || 1;// "pixelHeight = 0" -> "1" + const pixelDepth = dataView.getUint32(KTX_FIELDS.PIXEL_DEPTH, littleEndian) || 1;// ^^ + const numberOfArrayElements = dataView.getUint32(KTX_FIELDS.NUMBER_OF_ARRAY_ELEMENTS, littleEndian) || 1;// ^^ + const numberOfFaces = dataView.getUint32(KTX_FIELDS.NUMBER_OF_FACES, littleEndian); + const numberOfMipmapLevels = dataView.getUint32(KTX_FIELDS.NUMBER_OF_MIPMAP_LEVELS, littleEndian); + const bytesOfKeyValueData = dataView.getUint32(KTX_FIELDS.BYTES_OF_KEY_VALUE_DATA, littleEndian); + + // Whether the platform architecture is little endian. If littleEndian !== platformLittleEndian, then the + // file contents must be endian-converted! + // TODO: Endianness conversion + // const platformLittleEndian = new Uint8Array((new Uint32Array([ENDIANNESS])).buffer)[0] === 0x01; + + if (pixelHeight === 0 || pixelDepth !== 1) + { + throw new Error('Only 2D textures are supported'); + } + if (numberOfFaces !== 1) + { + throw new Error('CubeTextures are not supported by KTXLoader yet!'); + } + if (numberOfArrayElements !== 1) + { + // TODO: Support splitting array-textures into multiple BaseTextures + throw new Error('WebGL does not support array textures'); + } + + // TODO: 8x4 blocks for 2bpp pvrtc + const blockWidth = 4; + const blockHeight = 4; + + const alignedWidth = (pixelWidth + 3) & ~3; + const alignedHeight = (pixelHeight + 3) & ~3; + const imageBuffers = new Array(numberOfArrayElements); + let imagePixels = pixelWidth * pixelHeight; + + if (glType === 0) + { + // Align to 16 pixels (4x4 blocks) + imagePixels = alignedWidth * alignedHeight; + } + + let imagePixelByteSize: number; + + if (glType !== 0) + { + // Uncompressed texture format + if (TYPES_TO_BYTES_PER_COMPONENT[glType]) + { + imagePixelByteSize = TYPES_TO_BYTES_PER_COMPONENT[glType] * FORMATS_TO_COMPONENTS[glFormat]; + } + else + { + imagePixelByteSize = TYPES_TO_BYTES_PER_PIXEL[glType]; + } + } + else + { + imagePixelByteSize = INTERNAL_FORMAT_TO_BYTES_PER_PIXEL[glInternalFormat]; + } + + if (imagePixelByteSize === undefined) + { + throw new Error('Unable to resolve the pixel format stored in the *.ktx file!'); + } + + const kvData: Map | null = loadKeyValueData + ? parseKvData(dataView, bytesOfKeyValueData, littleEndian) + : null; + + const imageByteSize = imagePixels * imagePixelByteSize; + let mipByteSize = imageByteSize; + let mipWidth = pixelWidth; + let mipHeight = pixelHeight; + let alignedMipWidth = alignedWidth; + let alignedMipHeight = alignedHeight; + let imageOffset = FILE_HEADER_SIZE + bytesOfKeyValueData; + + for (let mipmapLevel = 0; mipmapLevel < numberOfMipmapLevels; mipmapLevel++) + { + const imageSize = dataView.getUint32(imageOffset, littleEndian); + let elementOffset = imageOffset + 4; + + for (let arrayElement = 0; arrayElement < numberOfArrayElements; arrayElement++) + { + // TODO: Maybe support 3D textures? :-) + // for (let zSlice = 0; zSlice < pixelDepth; zSlice) + + let mips = imageBuffers[arrayElement]; + + if (!mips) + { + mips = imageBuffers[arrayElement] = new Array(numberOfMipmapLevels); + } + + mips[mipmapLevel] = { + levelID: mipmapLevel, + + // don't align mipWidth when texture not compressed! (glType not zero) + levelWidth: numberOfMipmapLevels > 1 || glType !== 0 ? mipWidth : alignedMipWidth, + levelHeight: numberOfMipmapLevels > 1 || glType !== 0 ? mipHeight : alignedMipHeight, + levelBuffer: new Uint8Array(arrayBuffer, elementOffset, mipByteSize) + }; + elementOffset += mipByteSize; + } + + // HINT: Aligns to 4-byte boundary after jumping imageSize (in lieu of mipPadding) + imageOffset += imageSize + 4;// (+4 to jump the imageSize field itself) + imageOffset = imageOffset % 4 !== 0 ? imageOffset + 4 - (imageOffset % 4) : imageOffset; + + // Calculate mipWidth, mipHeight for _next_ iteration + mipWidth = (mipWidth >> 1) || 1; + mipHeight = (mipHeight >> 1) || 1; + alignedMipWidth = (mipWidth + blockWidth - 1) & ~(blockWidth - 1); + alignedMipHeight = (mipHeight + blockHeight - 1) & ~(blockHeight - 1); + + // Each mipmap level is 4-times smaller? + mipByteSize = alignedMipWidth * alignedMipHeight * imagePixelByteSize; + } + + // We use the levelBuffers feature of CompressedTextureResource b/c texture data is image-major, not level-major. + if (glType !== 0) + { + return { + uncompressed: imageBuffers.map((levelBuffers) => + { + let buffer: Float32Array | Uint32Array | Int32Array | Uint8Array = levelBuffers[0].levelBuffer; + let convertToInt = false; + + if (glType === TYPES.FLOAT) + { + buffer = new Float32Array( + levelBuffers[0].levelBuffer.buffer, + levelBuffers[0].levelBuffer.byteOffset, + levelBuffers[0].levelBuffer.byteLength / 4); + } + else if (glType === TYPES.UNSIGNED_INT) + { + convertToInt = true; + buffer = new Uint32Array( + levelBuffers[0].levelBuffer.buffer, + levelBuffers[0].levelBuffer.byteOffset, + levelBuffers[0].levelBuffer.byteLength / 4); + } + else if (glType === TYPES.INT) + { + convertToInt = true; + buffer = new Int32Array( + levelBuffers[0].levelBuffer.buffer, + levelBuffers[0].levelBuffer.byteOffset, + levelBuffers[0].levelBuffer.byteLength / 4); + } + + return { + resource: new BufferResource( + buffer, + { + width: levelBuffers[0].levelWidth, + height: levelBuffers[0].levelHeight, + } + ), + type: glType, + format: convertToInt ? convertFormatToInteger(glFormat) : glFormat, + }; + }), + kvData + }; + } + + return { + compressed: imageBuffers.map((levelBuffers) => new CompressedTextureResource(null, { + format: glInternalFormat, + width: pixelWidth, + height: pixelHeight, + levels: numberOfMipmapLevels, + levelBuffers, + })), + kvData + }; +} + +/** + * Checks whether the arrayBuffer contains a valid *.ktx file. + * @param url + * @param dataView + */ +function validate(url: string, dataView: DataView): boolean +{ + // NOTE: Do not optimize this into 3 32-bit integer comparison because the endianness + // of the data is not specified. + for (let i = 0; i < FILE_IDENTIFIER.length; i++) + { + if (dataView.getUint8(i) !== FILE_IDENTIFIER[i]) + { + // #if _DEBUG + console.error(`${url} is not a valid *.ktx file!`); + // #endif + + return false; + } + } + + return true; +} + +function convertFormatToInteger(format: FORMATS) +{ + switch (format) + { + case FORMATS.RGBA: return FORMATS.RGBA_INTEGER; + case FORMATS.RGB: return FORMATS.RGB_INTEGER; + case FORMATS.RG: return FORMATS.RG_INTEGER; + case FORMATS.RED: return FORMATS.RED_INTEGER; + default: return format; + } +} + +function parseKvData(dataView: DataView, bytesOfKeyValueData: number, littleEndian: boolean): Map +{ + const kvData = new Map(); + let bytesIntoKeyValueData = 0; + + while (bytesIntoKeyValueData < bytesOfKeyValueData) + { + const keyAndValueByteSize = dataView.getUint32(FILE_HEADER_SIZE + bytesIntoKeyValueData, littleEndian); + const keyAndValueByteOffset = FILE_HEADER_SIZE + bytesIntoKeyValueData + 4; + const valuePadding = 3 - ((keyAndValueByteSize + 3) % 4); + + // Bounds check + if (keyAndValueByteSize === 0 || keyAndValueByteSize > bytesOfKeyValueData - bytesIntoKeyValueData) + { + console.error('KTXLoader: keyAndValueByteSize out of bounds'); + break; + } + + // Note: keyNulByte can't be 0 otherwise the key is an empty string. + let keyNulByte = 0; + + for (; keyNulByte < keyAndValueByteSize; keyNulByte++) + { + if (dataView.getUint8(keyAndValueByteOffset + keyNulByte) === 0x00) + { + break; + } + } + + if (keyNulByte === -1) + { + console.error('KTXLoader: Failed to find null byte terminating kvData key'); + break; + } + + const key = new TextDecoder().decode( + new Uint8Array(dataView.buffer, keyAndValueByteOffset, keyNulByte) + ); + const value = new DataView( + dataView.buffer, + keyAndValueByteOffset + keyNulByte + 1, + keyAndValueByteSize - keyNulByte - 1, + ); + + kvData.set(key, value); + + // 4 = the keyAndValueByteSize field itself + // keyAndValueByteSize = the bytes taken by the key and value + // valuePadding = extra padding to align with 4 bytes + bytesIntoKeyValueData += 4 + keyAndValueByteSize + valuePadding; + } + + return kvData; +} diff --git a/packages/compressed-textures/src/resources/BlobResource.ts b/packages/compressed-textures/src/resources/BlobResource.ts index e2d4f9b8639..c0c9b27b164 100644 --- a/packages/compressed-textures/src/resources/BlobResource.ts +++ b/packages/compressed-textures/src/resources/BlobResource.ts @@ -1,4 +1,5 @@ -import { Resource, ViewableBuffer, BufferResource } from '@pixi/core'; +import type { Resource } from '@pixi/core'; +import { ViewableBuffer, BufferResource } from '@pixi/core'; interface IBlobOptions { @@ -9,7 +10,6 @@ interface IBlobOptions /** * Resource that fetches texture data over the network and stores it in a buffer. - * * @class * @extends PIXI.Resource * @memberof PIXI @@ -21,9 +21,12 @@ export abstract class BlobResource extends BufferResource protected loaded: boolean; /** - * @param {string} url - the URL of the texture file - * @param {boolean}[autoLoad] - whether to fetch the data immediately; + * @param {string} source - the URL of the texture file + * @param {PIXI.IBlobOptions} options + * @param {boolean}[options.autoLoad] - whether to fetch the data immediately; * you can fetch it later via {@link BlobResource#load} + * @param {boolean}[options.width] - the width in pixels. + * @param {boolean}[options.height] - the height in pixels. */ constructor(source: string | Uint8Array | Uint32Array | Float32Array, options: IBlobOptions = { width: 1, height: 1, autoLoad: true }) @@ -62,7 +65,7 @@ export abstract class BlobResource extends BufferResource { this.load(); } - if (data && data.length) + if (data?.length) { this.loaded = true; this.onBlobLoaded(this.buffer.rawBinaryData); @@ -74,9 +77,7 @@ export abstract class BlobResource extends BufferResource // TODO: Override this method } - /** - * Loads the blob - */ + /** Loads the blob */ async load(): Promise { const response = await fetch(this.origin); diff --git a/packages/compressed-textures/src/resources/CompressedTextureResource.ts b/packages/compressed-textures/src/resources/CompressedTextureResource.ts index cf024839cac..229ac78dd6f 100644 --- a/packages/compressed-textures/src/resources/CompressedTextureResource.ts +++ b/packages/compressed-textures/src/resources/CompressedTextureResource.ts @@ -1,13 +1,13 @@ import { BlobResource } from './BlobResource'; import { INTERNAL_FORMAT_TO_BYTES_PER_PIXEL } from '../const'; -import { Renderer, BaseTexture, GLTexture } from '@pixi/core'; +import type { Renderer, BaseTexture, GLTexture } from '@pixi/core'; import type { INTERNAL_FORMATS } from '../const'; /** + * Used in parseKTX * @ignore */ -// Used in PIXI.KTXLoader export type CompressedLevelBuffer = { levelID: number, levelWidth: number, @@ -35,15 +35,16 @@ export interface ICompressedTextureResourceOptions * more detail in the same amount of memory. * * For most developers, container file formats are a better abstraction instead of directly handling raw texture - * data. PixiJS provides native support for the following texture file formats (via {@link PIXI.Loader}): + * data. PixiJS provides native support for the following texture file formats + * (via {@link PIXI.loadBasis}, {@link PIXI.loadKTX}, and {@link PIXI.loadDDS}): * - * * **.dds** - the DirectDraw Surface file format stores DXTn (DXT-1,3,5) data. See {@link PIXI.DDSLoader} - * * **.ktx** - the Khronos Texture Container file format supports storing all the supported WebGL compression formats. - * See {@link PIXI.KTXLoader}. - * * **.basis** - the BASIS supercompressed file format stores texture data in an internal format that is transcoded + * **.dds** - the DirectDraw Surface file format stores DXTn (DXT-1,3,5) data. See {@link PIXI.parseDDS} + * **.ktx** - the Khronos Texture Container file format supports storing all the supported WebGL compression formats. + * See {@link PIXI.parseKTX}. + * **.basis** - the BASIS supercompressed file format stores texture data in an internal format that is transcoded * to the compression format supported on the device at _runtime_. It also supports transcoding into a uncompressed * format as a fallback; you must install the `@pixi/basis-loader`, `@pixi/basis-transcoder` packages separately to - * use these files. See {@link PIXI.BasisLoader}. + * use these files. See {@link PIXI.BasisParser}. * * The loaders for the aforementioned formats use `CompressedTextureResource` internally. It is strongly suggested that * they be used instead. @@ -73,7 +74,6 @@ export interface ICompressedTextureResourceOptions * PIXI.BaseTexture.addToCache(baseTexture, "bunny.dxt5"); * PIXI.Texture.addToCache(texture, "bunny.dxt5"); * ``` - * * @memberof PIXI */ export class CompressedTextureResource extends BlobResource @@ -172,13 +172,12 @@ export class CompressedTextureResource extends BlobResource /** * Returns the key (to ContextSystem#extensions) for the WebGL extension supporting the compression format - * * @private * @param format - the compression format to get the extension for. */ private static _formatToExtension(format: INTERNAL_FORMATS): - 's3tc' | 's3tc_sRGB' | 'atc' | - 'astc' | 'etc' | 'etc1' | 'pvrtc' + 's3tc' | 's3tc_sRGB' | 'atc' | + 'astc' | 'etc' | 'etc1' | 'pvrtc' { if (format >= 0x83F0 && format <= 0x83F3) { @@ -206,7 +205,6 @@ export class CompressedTextureResource extends BlobResource /** * Pre-creates buffer views for each mipmap level - * * @private * @param buffer - * @param format - compression formats diff --git a/packages/compressed-textures/test/compressed-textures.tests.ts b/packages/compressed-textures/test/compressed-textures.tests.ts new file mode 100644 index 00000000000..486ac5a15d7 --- /dev/null +++ b/packages/compressed-textures/test/compressed-textures.tests.ts @@ -0,0 +1,90 @@ +import { Assets } from '@pixi/assets'; +import type { Texture } from '@pixi/core'; +import { Loader } from '../../assets/src/loader/Loader'; +import { Resolver } from '../../assets/src/resolver/Resolver'; +import { detectCompressedTextures, loadDDS, loadKTX, resolveCompressedTextureUrl } from '../src/loaders'; + +describe('Compressed Loader', () => +{ + beforeEach(() => Assets.reset()); + + it('should load a ktx image', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadKTX); + + // eslint-disable-next-line max-len + const texture: Texture = await loader.load(`https://pixijs.io/compressed-textures-example/images/PixiJS-Logo_PNG_BC3_KTX.KTX`); + + expect(texture.baseTexture.valid).toBe(true); + expect(texture.width).toBe(898); + expect(texture.height).toBe(227); + }); + + it('should load a a DDS image', async () => + { + const loader = new Loader(); + + loader['_parsers'].push(loadDDS); + + // eslint-disable-next-line max-len + const texture: Texture = await loader.load(`https://pixijs.io/compressed-textures-example/images/airplane-boeing_JPG_BC3_1.DDS`); + + expect(texture.baseTexture.valid).toBe(true); + expect(texture.width).toBe(1000); + expect(texture.height).toBe(664); + }); + + it('should resolve asset', () => + { + const resolver = new Resolver(); + + resolver['_parsers'].push(resolveCompressedTextureUrl); + + resolver.prefer({ + priority: ['format'], + params: { + format: ['s3tc', 's3tc_sRGB', 'png', 'webp'], + resolution: 1 + } + }); + + resolver.add('test', [ + { + resolution: 1, + format: 'png', + src: 'my-image.png', + }, + { + resolution: 1, + format: 'webp', + src: 'my-image.webp', + }, + { + resolution: 1, + format: 's3tc', + src: 'my-image.s3tc.ktx', + }, + ]); + + const asset = resolver.resolveUrl('test'); + + expect(asset).toEqual('my-image.s3tc.ktx'); + }); + + it('should add compressed texture formats', async () => + { + await Assets.init(); + expect((Assets.resolver['_preferredOrder'][0].params.format as string[]).includes('s3tc')).toBe(true); + }); + + it('should remove any unsupported formats', async () => + { + detectCompressedTextures.test = jest.fn(async () => false); + await Assets.init(); + expect(Assets.resolver['_preferredOrder'][0].params.format).toEqual( + ['avif', 'webp', 'png', 'jpg', 'jpeg'] + ); + }); +}); diff --git a/packages/constants/package.json b/packages/constants/package.json index 2c851334ab5..0e9b8ef5320 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/constants", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/constants.js", - "module": "dist/esm/constants.js", - "bundle": "dist/browser/constants.js", + "module": "dist/esm/constants.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/constants.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/constants.js" + } + } + }, "description": "Constants used across PixiJS", "author": "Mat Groves", "contributors": [ @@ -20,7 +32,6 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ] diff --git a/packages/constants/src/index.ts b/packages/constants/src/index.ts index 1c4ba808527..f72faf728fa 100644 --- a/packages/constants/src/index.ts +++ b/packages/constants/src/index.ts @@ -1,6 +1,5 @@ /** * Different types of environments for WebGL. - * * @static * @memberof PIXI * @name ENV @@ -10,7 +9,9 @@ * @property {number} WEBGL - Version 1 of WebGL * @property {number} WEBGL2 - Version 2 of WebGL */ -export enum ENV { +export enum ENV +// eslint-disable-next-line @typescript-eslint/indent +{ WEBGL_LEGACY, WEBGL, WEBGL2, @@ -18,7 +19,6 @@ export enum ENV { /** * Constant to identify the Renderer Type. - * * @static * @memberof PIXI * @name RENDERER_TYPE @@ -27,7 +27,9 @@ export enum ENV { * @property {number} WEBGL - WebGL render type. * @property {number} CANVAS - Canvas render type. */ -export enum RENDERER_TYPE { +export enum RENDERER_TYPE +// eslint-disable-next-line @typescript-eslint/indent +{ UNKNOWN, WEBGL, CANVAS, @@ -35,7 +37,6 @@ export enum RENDERER_TYPE { /** * Bitwise OR of masks that indicate the buffers to be cleared. - * * @static * @memberof PIXI * @name BUFFER_BITS @@ -44,7 +45,9 @@ export enum RENDERER_TYPE { * @property {number} DEPTH - Indicates the depth buffer. * @property {number} STENCIL - Indicates the stencil buffer. */ -export enum BUFFER_BITS { +export enum BUFFER_BITS +// eslint-disable-next-line @typescript-eslint/indent +{ COLOR = 0x00004000, DEPTH = 0x00000100, STENCIL = 0x00000400 @@ -55,44 +58,45 @@ export enum BUFFER_BITS { * * IMPORTANT - The WebGL renderer only supports the NORMAL, ADD, MULTIPLY and SCREEN blend modes. * Anything else will silently act like NORMAL. - * * @memberof PIXI * @name BLEND_MODES * @enum {number} - * @property {number} NORMAL - * @property {number} ADD - * @property {number} MULTIPLY - * @property {number} SCREEN - * @property {number} OVERLAY - * @property {number} DARKEN - * @property {number} LIGHTEN - * @property {number} COLOR_DODGE - * @property {number} COLOR_BURN - * @property {number} HARD_LIGHT - * @property {number} SOFT_LIGHT - * @property {number} DIFFERENCE - * @property {number} EXCLUSION - * @property {number} HUE - * @property {number} SATURATION - * @property {number} COLOR - * @property {number} LUMINOSITY - * @property {number} NORMAL_NPM - * @property {number} ADD_NPM - * @property {number} SCREEN_NPM - * @property {number} NONE - * @property {number} SRC_IN - * @property {number} SRC_OUT - * @property {number} SRC_ATOP - * @property {number} DST_OVER - * @property {number} DST_IN - * @property {number} DST_OUT - * @property {number} DST_ATOP - * @property {number} SUBTRACT - * @property {number} SRC_OVER - * @property {number} ERASE - * @property {number} XOR + * @property {number} NORMAL - + * @property {number} ADD - + * @property {number} MULTIPLY - + * @property {number} SCREEN - + * @property {number} OVERLAY - + * @property {number} DARKEN - + * @property {number} LIGHTEN - + * @property {number} COLOR_DODGE - + * @property {number} COLOR_BURN - + * @property {number} HARD_LIGHT - + * @property {number} SOFT_LIGHT - + * @property {number} DIFFERENCE - + * @property {number} EXCLUSION - + * @property {number} HUE - + * @property {number} SATURATION - + * @property {number} COLOR - + * @property {number} LUMINOSITY - + * @property {number} NORMAL_NPM - + * @property {number} ADD_NPM - + * @property {number} SCREEN_NPM - + * @property {number} NONE - + * @property {number} SRC_IN - + * @property {number} SRC_OUT - + * @property {number} SRC_ATOP - + * @property {number} DST_OVER - + * @property {number} DST_IN - + * @property {number} DST_OUT - + * @property {number} DST_ATOP - + * @property {number} SUBTRACT - + * @property {number} SRC_OVER - + * @property {number} ERASE - + * @property {number} XOR - */ -export enum BLEND_MODES { +export enum BLEND_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ NORMAL = 0, ADD = 1, MULTIPLY = 2, @@ -131,20 +135,21 @@ export enum BLEND_MODES { /** * Various webgl draw modes. These can be used to specify which GL drawMode to use * under certain situations and renderers. - * * @memberof PIXI * @static * @name DRAW_MODES * @enum {number} - * @property {number} POINTS - * @property {number} LINES - * @property {number} LINE_LOOP - * @property {number} LINE_STRIP - * @property {number} TRIANGLES - * @property {number} TRIANGLE_STRIP - * @property {number} TRIANGLE_FAN + * @property {number} POINTS - + * @property {number} LINES - + * @property {number} LINE_LOOP - + * @property {number} LINE_STRIP - + * @property {number} TRIANGLES - + * @property {number} TRIANGLE_STRIP - + * @property {number} TRIANGLE_FAN - */ -export enum DRAW_MODES { +export enum DRAW_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ POINTS, LINES, LINE_LOOP, @@ -156,26 +161,27 @@ export enum DRAW_MODES { /** * Various GL texture/resources formats. - * * @memberof PIXI * @static * @name FORMATS * @enum {number} - * @property {number} RGBA=6408 - * @property {number} RGB=6407 - * @property {number} RG=33319 - * @property {number} RED=6403 - * @property {number} RGBA_INTEGER=36249 - * @property {number} RGB_INTEGER=36248 - * @property {number} RG_INTEGER=33320 - * @property {number} RED_INTEGER=36244 - * @property {number} ALPHA=6406 - * @property {number} LUMINANCE=6409 - * @property {number} LUMINANCE_ALPHA=6410 - * @property {number} DEPTH_COMPONENT=6402 - * @property {number} DEPTH_STENCIL=34041 + * @property {number} [RGBA=6408] - + * @property {number} [RGB=6407] - + * @property {number} [RG=33319] - + * @property {number} [RED=6403] - + * @property {number} [RGBA_INTEGER=36249] - + * @property {number} [RGB_INTEGER=36248] - + * @property {number} [RG_INTEGER=33320] - + * @property {number} [RED_INTEGER=36244] - + * @property {number} [ALPHA=6406] - + * @property {number} [LUMINANCE=6409] - + * @property {number} [LUMINANCE_ALPHA=6410] - + * @property {number} [DEPTH_COMPONENT=6402] - + * @property {number} [DEPTH_STENCIL=34041] - */ -export enum FORMATS { +export enum FORMATS +// eslint-disable-next-line @typescript-eslint/indent +{ RGBA = 6408, RGB = 6407, RG = 33319, @@ -193,22 +199,23 @@ export enum FORMATS { /** * Various GL target types. - * * @memberof PIXI * @static * @name TARGETS * @enum {number} - * @property {number} TEXTURE_2D=3553 - * @property {number} TEXTURE_CUBE_MAP=34067 - * @property {number} TEXTURE_2D_ARRAY=35866 - * @property {number} TEXTURE_CUBE_MAP_POSITIVE_X=34069 - * @property {number} TEXTURE_CUBE_MAP_NEGATIVE_X=34070 - * @property {number} TEXTURE_CUBE_MAP_POSITIVE_Y=34071 - * @property {number} TEXTURE_CUBE_MAP_NEGATIVE_Y=34072 - * @property {number} TEXTURE_CUBE_MAP_POSITIVE_Z=34073 - * @property {number} TEXTURE_CUBE_MAP_NEGATIVE_Z=34074 + * @property {number} [TEXTURE_2D=3553] - + * @property {number} [TEXTURE_CUBE_MAP=34067] - + * @property {number} [TEXTURE_2D_ARRAY=35866] - + * @property {number} [TEXTURE_CUBE_MAP_POSITIVE_X=34069] - + * @property {number} [TEXTURE_CUBE_MAP_NEGATIVE_X=34070] - + * @property {number} [TEXTURE_CUBE_MAP_POSITIVE_Y=34071] - + * @property {number} [TEXTURE_CUBE_MAP_NEGATIVE_Y=34072] - + * @property {number} [TEXTURE_CUBE_MAP_POSITIVE_Z=34073] - + * @property {number} [TEXTURE_CUBE_MAP_NEGATIVE_Z=34074] - */ -export enum TARGETS { +export enum TARGETS +// eslint-disable-next-line @typescript-eslint/indent +{ TEXTURE_2D = 3553, TEXTURE_CUBE_MAP = 34067, TEXTURE_2D_ARRAY = 35866, @@ -222,29 +229,30 @@ export enum TARGETS { /** * Various GL data format types. - * * @memberof PIXI * @static * @name TYPES * @enum {number} - * @property {number} UNSIGNED_BYTE=5121 - * @property {number} UNSIGNED_SHORT=5123 - * @property {number} UNSIGNED_SHORT_5_6_5=33635 - * @property {number} UNSIGNED_SHORT_4_4_4_4=32819 - * @property {number} UNSIGNED_SHORT_5_5_5_1=32820 - * @property {number} UNSIGNED_INT=5125 - * @property {number} UNSIGNED_INT_10F_11F_11F_REV=35899 - * @property {number} UNSIGNED_INT_2_10_10_10_REV=33640 - * @property {number} UNSIGNED_INT_24_8=34042 - * @property {number} UNSIGNED_INT_5_9_9_9_REV=35902 - * @property {number} BYTE=5120 - * @property {number} SHORT=5122 - * @property {number} INT=5124 - * @property {number} FLOAT=5126 - * @property {number} FLOAT_32_UNSIGNED_INT_24_8_REV=36269 - * @property {number} HALF_FLOAT=36193 + * @property {number} [UNSIGNED_BYTE=5121] - + * @property {number} [UNSIGNED_SHORT=5123] - + * @property {number} [UNSIGNED_SHORT_5_6_5=33635] - + * @property {number} [UNSIGNED_SHORT_4_4_4_4=32819] - + * @property {number} [UNSIGNED_SHORT_5_5_5_1=32820] - + * @property {number} [UNSIGNED_INT=5125] - + * @property {number} [UNSIGNED_INT_10F_11F_11F_REV=35899] - + * @property {number} [UNSIGNED_INT_2_10_10_10_REV=33640] - + * @property {number} [UNSIGNED_INT_24_8=34042] - + * @property {number} [UNSIGNED_INT_5_9_9_9_REV=35902] - + * @property {number} [BYTE=5120] - + * @property {number} [SHORT=5122] - + * @property {number} [INT=5124] - + * @property {number} [FLOAT=5126] - + * @property {number} [FLOAT_32_UNSIGNED_INT_24_8_REV=36269] - + * @property {number} [HALF_FLOAT=36193] - */ -export enum TYPES { +export enum TYPES +// eslint-disable-next-line @typescript-eslint/indent +{ UNSIGNED_BYTE = 5121, UNSIGNED_SHORT = 5123, UNSIGNED_SHORT_5_6_5 = 33635, @@ -266,16 +274,17 @@ export enum TYPES { /** * Various sampler types. Correspond to `sampler`, `isampler`, `usampler` GLSL types respectively. * WebGL1 works only with FLOAT. - * * @memberof PIXI * @static * @name SAMPLER_TYPES * @enum {number} - * @property {number} FLOAT=0 - * @property {number} INT=1 - * @property {number} UINT=2 + * @property {number} [FLOAT=0] - + * @property {number} [INT=1] - + * @property {number} [UINT=2] - */ -export enum SAMPLER_TYPES { +export enum SAMPLER_TYPES +// eslint-disable-next-line @typescript-eslint/indent +{ FLOAT = 0, INT = 1, UINT = 2, @@ -286,7 +295,6 @@ export enum SAMPLER_TYPES { * * The {@link PIXI.settings.SCALE_MODE} scale mode affects the default scaling mode of future operations. * It can be re-assigned to either LINEAR or NEAREST, depending upon suitability. - * * @memberof PIXI * @static * @name SCALE_MODES @@ -294,7 +302,9 @@ export enum SAMPLER_TYPES { * @property {number} LINEAR Smooth scaling * @property {number} NEAREST Pixelating scaling */ -export enum SCALE_MODES { +export enum SCALE_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ NEAREST, LINEAR, } @@ -308,7 +318,6 @@ export enum SCALE_MODES { * only use REPEAT if the texture is po2. * * This property only affects WebGL. - * * @name WRAP_MODES * @memberof PIXI * @static @@ -317,7 +326,9 @@ export enum SCALE_MODES { * @property {number} REPEAT - The texture uvs tile and repeat * @property {number} MIRRORED_REPEAT - The texture uvs tile and repeat with mirroring */ -export enum WRAP_MODES { +export enum WRAP_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ CLAMP = 33071, REPEAT = 10497, MIRRORED_REPEAT = 33648, @@ -332,7 +343,6 @@ export enum WRAP_MODES { * Due to platform restriction, `ON` option will work like `POW2` for webgl-1. * * This property only affects WebGL. - * * @name MIPMAP_MODES * @memberof PIXI * @static @@ -343,7 +353,9 @@ export enum WRAP_MODES { * @property {number} ON_MANUAL - Use mipmaps, but do not auto-generate them; this is used with a resource * that supports buffering each level-of-detail. */ -export enum MIPMAP_MODES { +export enum MIPMAP_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ OFF, POW2, ON, @@ -352,7 +364,6 @@ export enum MIPMAP_MODES { /** * How to treat textures with premultiplied alpha - * * @name ALPHA_MODES * @memberof PIXI * @static @@ -367,13 +378,14 @@ export enum MIPMAP_MODES { * @property {number} UNPACK - Default option, alias for PREMULTIPLY_ON_UPLOAD. * @property {number} PMA - Alias for PREMULTIPLIED_ALPHA. */ -export enum ALPHA_MODES { +export enum ALPHA_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ NPM = 0, UNPACK = 1, PMA = 2, NO_PREMULTIPLIED_ALPHA = 0, PREMULTIPLY_ON_UPLOAD = 1, - PREMULTIPLY_ALPHA = 2, // deprecated, undocumented PREMULTIPLIED_ALPHA = 2, } @@ -382,7 +394,6 @@ export enum ALPHA_MODES { * * Filter textures need not be cleared if the filter does not use pixel blending. {@link CLEAR_MODES.BLIT} will detect * this and skip clearing as an optimization. - * * @name CLEAR_MODES * @memberof PIXI * @static @@ -394,7 +405,9 @@ export enum ALPHA_MODES { * @property {number} YES - Alias for CLEAR, same as `true` in earlier versions * @property {number} AUTO - Alias for BLIT */ -export enum CLEAR_MODES { +export enum CLEAR_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ NO = 0, YES = 1, AUTO = 2, @@ -414,7 +427,6 @@ export enum CLEAR_MODES { * * Handy for mobile devices! * This property only affects WebGL. - * * @name GC_MODES * @enum {number} * @static @@ -422,24 +434,27 @@ export enum CLEAR_MODES { * @property {number} AUTO - Garbage collection will happen periodically automatically * @property {number} MANUAL - Garbage collection will need to be called manually */ -export enum GC_MODES { +export enum GC_MODES +// eslint-disable-next-line @typescript-eslint/indent +{ AUTO, MANUAL, } /** * Constants that specify float precision in shaders. - * * @name PRECISION * @memberof PIXI * @constant * @static * @enum {string} - * @property {string} LOW='lowp' - * @property {string} MEDIUM='mediump' - * @property {string} HIGH='highp' + * @property {string} [LOW='lowp'] - + * @property {string} [MEDIUM='mediump'] - + * @property {string} [HIGH='highp'] - */ -export enum PRECISION { +export enum PRECISION +// eslint-disable-next-line @typescript-eslint/indent +{ LOW = 'lowp', MEDIUM = 'mediump', HIGH = 'highp', @@ -448,7 +463,6 @@ export enum PRECISION { /** * Constants for mask implementations. * We use `type` suffix because it leads to very different behaviours - * * @name MASK_TYPES * @memberof PIXI * @static @@ -457,19 +471,41 @@ export enum PRECISION { * @property {number} SCISSOR - Scissor mask, rectangle on screen, cheap * @property {number} STENCIL - Stencil mask, 1-bit, medium, works only if renderer supports stencil * @property {number} SPRITE - Mask that uses SpriteMaskFilter, uses temporary RenderTexture + * @property {number} COLOR - Color mask (RGBA) */ -export enum MASK_TYPES { +export enum MASK_TYPES +// eslint-disable-next-line @typescript-eslint/indent +{ NONE = 0, SCISSOR = 1, STENCIL = 2, SPRITE = 3, + COLOR = 4, +} + +/** + * Bitwise OR of masks that indicate the color channels that are rendered to. + * @static + * @memberof PIXI + * @name COLOR_MASK_BITS + * @enum {number} + * @property {number} RED - Red channel. + * @property {number} GREEN - Green channel + * @property {number} BLUE - Blue channel. + * @property {number} ALPHA - Alpha channel. + */ +export enum COLOR_MASK_BITS +// eslint-disable-next-line @typescript-eslint/indent +{ + RED = 0x1, + GREEN = 0x2, + BLUE = 0x4, + ALPHA = 0x8 } /** * Constants for multi-sampling antialiasing. - * * @see PIXI.Framebuffer#multisample - * * @name MSAA_QUALITY * @memberof PIXI * @static @@ -479,7 +515,9 @@ export enum MASK_TYPES { * @property {number} MEDIUM - Try 4 samples * @property {number} HIGH - Try 8 samples */ -export enum MSAA_QUALITY { +export enum MSAA_QUALITY +// eslint-disable-next-line @typescript-eslint/indent +{ NONE = 0, LOW = 2, MEDIUM = 4, @@ -488,9 +526,7 @@ export enum MSAA_QUALITY { /** * Constants for various buffer types in Pixi - * * @see PIXI.BUFFER_TYPE - * * @name BUFFER_TYPE * @memberof PIXI * @static @@ -499,7 +535,9 @@ export enum MSAA_QUALITY { * @property {number} ARRAY_BUFFER - buffer type for using attribute data * @property {number} UNIFORM_BUFFER - the buffer type is for uniform buffer objects */ -export enum BUFFER_TYPE { +export enum BUFFER_TYPE +// eslint-disable-next-line @typescript-eslint/indent +{ ELEMENT_ARRAY_BUFFER = 34963, ARRAY_BUFFER = 34962, // NOT YET SUPPORTED diff --git a/packages/constants/test/constants.tests.ts b/packages/constants/test/constants.tests.ts index fed5fa6ca55..86538505e4f 100644 --- a/packages/constants/test/constants.tests.ts +++ b/packages/constants/test/constants.tests.ts @@ -1,70 +1,69 @@ import * as lib from '@pixi/constants'; -import { expect } from 'chai'; -describe('Constants', function () +describe('Constants', () => { - it('should have ENV', function () + it('should have ENV', () => { - expect(lib.ENV).to.be.an('object'); + expect(lib.ENV).toBeObject(); }); - it('should have RENDERER_TYPE', function () + it('should have RENDERER_TYPE', () => { - expect(lib.RENDERER_TYPE).to.be.an('object'); + expect(lib.RENDERER_TYPE).toBeObject(); }); - it('should have BLEND_MODES', function () + it('should have BLEND_MODES', () => { - expect(lib.RENDERER_TYPE).to.be.an('object'); + expect(lib.RENDERER_TYPE).toBeObject(); }); - it('should have DRAW_MODES', function () + it('should have DRAW_MODES', () => { - expect(lib.DRAW_MODES).to.be.an('object'); + expect(lib.DRAW_MODES).toBeObject(); }); - it('should have FORMATS', function () + it('should have FORMATS', () => { - expect(lib.FORMATS).to.be.an('object'); + expect(lib.FORMATS).toBeObject(); }); - it('should have TARGETS', function () + it('should have TARGETS', () => { - expect(lib.TARGETS).to.be.an('object'); + expect(lib.TARGETS).toBeObject(); }); - it('should have TYPES', function () + it('should have TYPES', () => { - expect(lib.TYPES).to.be.an('object'); + expect(lib.TYPES).toBeObject(); }); - it('should have SCALE_MODES', function () + it('should have SCALE_MODES', () => { - expect(lib.SCALE_MODES).to.be.an('object'); + expect(lib.SCALE_MODES).toBeObject(); }); - it('should have WRAP_MODES', function () + it('should have WRAP_MODES', () => { - expect(lib.WRAP_MODES).to.be.an('object'); + expect(lib.WRAP_MODES).toBeObject(); }); - it('should have MIPMAP_MODES', function () + it('should have MIPMAP_MODES', () => { - expect(lib.MIPMAP_MODES).to.be.an('object'); + expect(lib.MIPMAP_MODES).toBeObject(); }); - it('should have ALPHA_MODES', function () + it('should have ALPHA_MODES', () => { - expect(lib.ALPHA_MODES).to.be.an('object'); + expect(lib.ALPHA_MODES).toBeObject(); }); - it('should have GC_MODES', function () + it('should have GC_MODES', () => { - expect(lib.GC_MODES).to.be.an('object'); + expect(lib.GC_MODES).toBeObject(); }); - it('should have PRECISION', function () + it('should have PRECISION', () => { - expect(lib.PRECISION).to.be.an('object'); + expect(lib.PRECISION).toBeObject(); }); }); diff --git a/packages/core/global.d.ts b/packages/core/global.d.ts index cbbebad7081..29ad46e51b4 100644 --- a/packages/core/global.d.ts +++ b/packages/core/global.d.ts @@ -23,4 +23,28 @@ declare namespace GlobalMixins { } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface IRenderableObject + { + + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface Renderer + { + + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface IRenderer + { + + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface IRendererPlugins + { + + } } diff --git a/packages/core/package.json b/packages/core/package.json index f987b5dc887..0466b990921 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/core", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/core.js", - "module": "dist/esm/core.js", - "bundle": "dist/browser/core.js", + "module": "dist/esm/core.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/core.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/core.js" + } + } + }, "description": "Core PixiJS", "author": "Mat Groves", "contributors": [ @@ -29,14 +41,13 @@ "url": "https://opencollective.com/pixijs" }, "dependencies": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/extensions": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/runner": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", + "@pixi/ticker": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha", "@types/offscreencanvas": "^2019.6.4" - }, - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/runner": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" } } diff --git a/packages/core/src/AbstractRenderer.ts b/packages/core/src/AbstractRenderer.ts deleted file mode 100644 index 7334f61c6cf..00000000000 --- a/packages/core/src/AbstractRenderer.ts +++ /dev/null @@ -1,464 +0,0 @@ -import { hex2string, hex2rgb, EventEmitter, deprecation } from '@pixi/utils'; -import { Matrix, Rectangle } from '@pixi/math'; -import { MSAA_QUALITY, RENDERER_TYPE } from '@pixi/constants'; -import { settings } from '@pixi/settings'; -import { RenderTexture } from './renderTexture/RenderTexture'; - -import type { SCALE_MODES } from '@pixi/constants'; -import type { ISystemConstructor } from './ISystem'; -import type { IRenderingContext } from './IRenderingContext'; -import type { IRenderableContainer, IRenderableObject } from './IRenderableObject'; - -const tempMatrix = new Matrix(); - -export interface IRendererOptions extends GlobalMixins.IRendererOptions -{ - width?: number; - height?: number; - view?: HTMLCanvasElement; - useContextAlpha?: boolean | 'notMultiplied'; - /** - * Use `backgroundAlpha` instead. - * @deprecated - */ - transparent?: boolean; - autoDensity?: boolean; - antialias?: boolean; - resolution?: number; - preserveDrawingBuffer?: boolean; - clearBeforeRender?: boolean; - backgroundColor?: number; - backgroundAlpha?: number; - powerPreference?: WebGLPowerPreference; - context?: IRenderingContext; -} - -export interface IRendererPlugins -{ - [key: string]: any; -} - -export interface IRendererRenderOptions { - renderTexture?: RenderTexture; - clear?: boolean; - transform?: Matrix; - skipUpdateTransform?: boolean; -} - -export interface IGenerateTextureOptions { - scaleMode?: SCALE_MODES; - resolution?: number; - region?: Rectangle; - multisample?: MSAA_QUALITY; -} - -/** - * The AbstractRenderer is the base for a PixiJS Renderer. It is extended by the {@link PIXI.CanvasRenderer} - * and {@link PIXI.Renderer} which can be used for rendering a PixiJS scene. - * - * @abstract - * @class - * @extends PIXI.utils.EventEmitter - * @memberof PIXI - */ -export abstract class AbstractRenderer extends EventEmitter -{ - public resolution: number; - public clearBeforeRender?: boolean; - public readonly options: IRendererOptions; - public readonly type: RENDERER_TYPE; - public readonly screen: Rectangle; - public readonly view: HTMLCanvasElement; - public readonly plugins: IRendererPlugins; - public readonly useContextAlpha: boolean | 'notMultiplied'; - public readonly autoDensity: boolean; - public readonly preserveDrawingBuffer: boolean; - - protected _backgroundColor: number; - protected _backgroundColorString: string; - _backgroundColorRgba: number[]; - _lastObjectRendered: IRenderableObject; - - /** - * @param system - The name of the system this renderer is for. - * @param [options] - The optional renderer parameters. - * @param {number} [options.width=800] - The width of the screen. - * @param {number} [options.height=600] - The height of the screen. - * @param {HTMLCanvasElement} [options.view] - The canvas to use as a view, optional. - * @param {boolean} [options.useContextAlpha=true] - Pass-through value for canvas' context `alpha` property. - * If you want to set transparency, please use `backgroundAlpha`. This option is for cases where the - * canvas needs to be opaque, possibly for performance reasons on some older devices. - * @param {boolean} [options.autoDensity=false] - Resizes renderer view in CSS pixels to allow for - * resolutions other than 1. - * @param {boolean} [options.antialias=false] - Sets antialias - * @param {number} [options.resolution=PIXI.settings.RESOLUTION] - The resolution / device pixel ratio of the renderer. - * @param {boolean} [options.preserveDrawingBuffer=false] - Enables drawing buffer preservation, - * enable this if you need to call toDataUrl on the WebGL context. - * @param {boolean} [options.clearBeforeRender=true] - This sets if the renderer will clear the canvas or - * not before the new render pass. - * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area - * (shown if not transparent). - * @param {number} [options.backgroundAlpha=1] - Value from 0 (fully transparent) to 1 (fully opaque). - */ - constructor(type: RENDERER_TYPE = RENDERER_TYPE.UNKNOWN, options?: IRendererOptions) - { - super(); - - // Add the default render options - options = Object.assign({}, settings.RENDER_OPTIONS, options); - - /** - * The supplied constructor options. - * - * @member {Object} - * @readOnly - */ - this.options = options; - - /** - * The type of the renderer. - * - * @member {number} - * @default PIXI.RENDERER_TYPE.UNKNOWN - * @see PIXI.RENDERER_TYPE - */ - this.type = type; - - /** - * Measurements of the screen. (0, 0, screenWidth, screenHeight). - * - * Its safe to use as filterArea or hitArea for the whole stage. - * - * @member {PIXI.Rectangle} - */ - this.screen = new Rectangle(0, 0, options.width, options.height); - - /** - * The canvas element that everything is drawn to. - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement('canvas'); - - /** - * The resolution / device pixel ratio of the renderer. - * - * @member {number} - * @default PIXI.settings.RESOLUTION - */ - this.resolution = options.resolution || settings.RESOLUTION; - - /** - * Pass-thru setting for the canvas' context `alpha` property. This is typically - * not something you need to fiddle with. If you want transparency, use `backgroundAlpha`. - * - * @member {boolean} - */ - this.useContextAlpha = options.useContextAlpha; - - /** - * Whether CSS dimensions of canvas view should be resized to screen dimensions automatically. - * - * @member {boolean} - */ - this.autoDensity = !!options.autoDensity; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of - * the stencil buffer is retained after rendering. - * - * @member {boolean} - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. - * If the scene is NOT transparent PixiJS will use a canvas sized fillRect operation every - * frame to set the canvas background color. If the scene is transparent PixiJS will use clearRect - * to clear the canvas every frame. Disable this by setting this to false. For example, if - * your game has a canvas filling background image you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The background color as a number. - * - * @member {number} - * @protected - */ - this._backgroundColor = 0x000000; - - /** - * The background color as an [R, G, B, A] array. - * - * @member {number[]} - * @protected - */ - this._backgroundColorRgba = [0, 0, 0, 1]; - - /** - * The background color as a string. - * - * @member {string} - * @protected - */ - this._backgroundColorString = '#000000'; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - this.backgroundAlpha = options.backgroundAlpha; - - // @deprecated - if (options.transparent !== undefined) - { - // #if _DEBUG - deprecation('6.0.0', 'Option transparent is deprecated, please use backgroundAlpha instead.'); - // #endif - this.useContextAlpha = options.transparent; - this.backgroundAlpha = options.transparent ? 0 : 1; - } - - /** - * The last root object that the renderer tried to render. - * - * @member {PIXI.DisplayObject} - * @protected - */ - this._lastObjectRendered = null; - - /** - * Collection of plugins. - * @readonly - * @member {object} - */ - this.plugins = {}; - } - - /** - * Initialize the plugins. - * - * @protected - * @param {object} staticMap - The dictionary of statically saved plugins. - */ - initPlugins(staticMap: IRendererPlugins): void - { - for (const o in staticMap) - { - this.plugins[o] = new (staticMap[o])(this); - } - } - - /** - * Same as view.width, actual number of pixels in the canvas by horizontal. - * - * @member {number} - * @readonly - * @default 800 - */ - get width(): number - { - return this.view.width; - } - - /** - * Same as view.height, actual number of pixels in the canvas by vertical. - * - * @member {number} - * @readonly - * @default 600 - */ - get height(): number - { - return this.view.height; - } - - /** - * Resizes the screen and canvas as close as possible to the specified width and height. - * Canvas dimensions are multiplied by resolution and rounded to the nearest integers. - * The new canvas dimensions divided by the resolution become the new screen dimensions. - * - * @param desiredScreenWidth - The desired width of the screen. - * @param desiredScreenHeight - The desired height of the screen. - */ - resize(desiredScreenWidth: number, desiredScreenHeight: number): void - { - this.view.width = Math.round(desiredScreenWidth * this.resolution); - this.view.height = Math.round(desiredScreenHeight * this.resolution); - - const screenWidth = this.view.width / this.resolution; - const screenHeight = this.view.height / this.resolution; - - this.screen.width = screenWidth; - this.screen.height = screenHeight; - - if (this.autoDensity) - { - this.view.style.width = `${screenWidth}px`; - this.view.style.height = `${screenHeight}px`; - } - - /** - * Fired after view has been resized. - * - * @event PIXI.Renderer#resize - * @param {number} screenWidth - The new width of the screen. - * @param {number} screenHeight - The new height of the screen. - */ - this.emit('resize', screenWidth, screenHeight); - } - - /** - * Useful function that returns a texture of the display object that can then be used to create sprites - * This can be quite useful if your displayObject is complicated and needs to be reused multiple times. - * @method PIXI.AbstractRenderer#generateTexture - * @param displayObject - The displayObject the object will be generated from. - * @param {object} options - Generate texture options. - * @param {PIXI.SCALE_MODES} options.scaleMode - The scale mode of the texture. - * @param {number} options.resolution - The resolution / device pixel ratio of the texture being generated. - * @param {PIXI.Rectangle} options.region - The region of the displayObject, that shall be rendered, - * if no region is specified, defaults to the local bounds of the displayObject. - * @param {PIXI.MSAA_QUALITY} options.multisample - The number of samples of the frame buffer. - * @return A texture of the graphics object. - */ - generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): RenderTexture; - - /** - * Please use the options argument instead. - * - * @method PIXI.AbstractRenderer#generateTexture - * @deprecated Since 6.1.0 - * @param displayObject - The displayObject the object will be generated from. - * @param scaleMode - The scale mode of the texture. - * @param resolution - The resolution / device pixel ratio of the texture being generated. - * @param region - The region of the displayObject, that shall be rendered, - * if no region is specified, defaults to the local bounds of the displayObject. - * @return A texture of the graphics object. - */ - generateTexture( - displayObject: IRenderableObject, - scaleMode?: SCALE_MODES, - resolution?: number, - region?: Rectangle): RenderTexture; - - /** - * @ignore - */ - generateTexture(displayObject: IRenderableObject, - options: IGenerateTextureOptions | SCALE_MODES = {}, - resolution?: number, region?: Rectangle): RenderTexture - { - // @deprecated parameters spread, use options instead - if (typeof options === 'number') - { - // #if _DEBUG - deprecation('6.1.0', 'generateTexture options (scaleMode, resolution, region) are now object options.'); - // #endif - - options = { scaleMode: options, resolution, region }; - } - - const { region: manualRegion, ...textureOptions } = options; - - region = manualRegion || (displayObject as IRenderableContainer).getLocalBounds(null, true); - - // minimum texture size is 1x1, 0x0 will throw an error - if (region.width === 0) region.width = 1; - if (region.height === 0) region.height = 1; - - const renderTexture = RenderTexture.create( - { - width: region.width, - height: region.height, - ...textureOptions, - }); - - tempMatrix.tx = -region.x; - tempMatrix.ty = -region.y; - - this.render(displayObject, { - renderTexture, - clear: false, - transform: tempMatrix, - skipUpdateTransform: !!displayObject.parent - }); - - return renderTexture; - } - - /** - * Adds a new system to the renderer. - * - * @param ClassRef - Class reference - * @param name - Property name for system - * @return Return instance of renderer - */ - abstract addSystem(ClassRef: ISystemConstructor, name: string): this; - - abstract render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void; - - /** - * Removes everything from the renderer and optionally removes the Canvas DOM element. - * - * @param [removeView=false] - Removes the Canvas element from the DOM. - */ - destroy(removeView?: boolean): void - { - for (const o in this.plugins) - { - this.plugins[o].destroy(); - this.plugins[o] = null; - } - - if (removeView && this.view.parentNode) - { - this.view.parentNode.removeChild(this.view); - } - - const thisAny = this as any; - - // null-ing all objects, that's a tradition! - - thisAny.plugins = null; - thisAny.type = RENDERER_TYPE.UNKNOWN; - thisAny.view = null; - thisAny.screen = null; - thisAny._tempDisplayObjectParent = null; - thisAny.options = null; - this._backgroundColorRgba = null; - this._backgroundColorString = null; - this._lastObjectRendered = null; - } - - /** - * The background color to fill if not transparent - * - * @member {number} - */ - get backgroundColor(): number - { - return this._backgroundColor; - } - - set backgroundColor(value: number) - { - this._backgroundColor = value; - this._backgroundColorString = hex2string(value); - hex2rgb(value, this._backgroundColorRgba); - } - - /** - * The background color alpha. Setting this to 0 will make the canvas transparent. - * - * @member {number} - */ - get backgroundAlpha(): number - { - return this._backgroundColorRgba[3]; - } - set backgroundAlpha(value: number) - { - this._backgroundColorRgba[3] = value; - } -} diff --git a/packages/core/src/IRenderableObject.ts b/packages/core/src/IRenderableObject.ts deleted file mode 100644 index 1247c5e8c45..00000000000 --- a/packages/core/src/IRenderableObject.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { Rectangle } from '@pixi/math'; -import type { Renderer } from './Renderer'; - -/** - * Interface for DisplayObject to interface with Renderer. - * The minimum APIs needed to implement a renderable object. - * @memberof PIXI - */ -interface IRenderableObject { - /** Object must have a parent container */ - parent: IRenderableContainer; - /** Before method for transform updates */ - enableTempParent(): IRenderableContainer; - /** Update the transforms */ - updateTransform(): void; - /** After method for transform updates */ - disableTempParent(parent: IRenderableContainer): void; - /** Render object directly */ - render(renderer: Renderer): void; -} - -/** - * Interface for Container to interface with Renderer. - * @memberof PIXI - */ -interface IRenderableContainer extends IRenderableObject { - /** Get Local bounds for container */ - getLocalBounds(rect?: Rectangle, skipChildrenUpdate?: boolean): Rectangle; -} - -export type { IRenderableObject, IRenderableContainer }; diff --git a/packages/core/src/IRenderer.ts b/packages/core/src/IRenderer.ts new file mode 100644 index 00000000000..8c36737b5fa --- /dev/null +++ b/packages/core/src/IRenderer.ts @@ -0,0 +1,119 @@ +import type { RENDERER_TYPE } from '@pixi/constants'; +import type { Matrix, Rectangle, Transform } from '@pixi/math'; +import type { IGenerateTextureOptions } from './renderTexture/GenerateTextureSystem'; +import type { IRendererPlugins } from './plugin/PluginSystem'; +import type { RenderTexture } from './renderTexture/RenderTexture'; +import type { SystemManager } from './system/SystemManager'; + +/** + * Interface for DisplayObject to interface with Renderer. + * The minimum APIs needed to implement a renderable object. + * @memberof PIXI + */ +export interface IRenderableObject extends GlobalMixins.IRenderableObject +{ + /** Object must have a parent container */ + parent: IRenderableContainer; + /** Object must have a transform */ + transform: Transform; + /** Before method for transform updates */ + enableTempParent(): IRenderableContainer; + /** Update the transforms */ + updateTransform(): void; + /** After method for transform updates */ + disableTempParent(parent: IRenderableContainer): void; + /** Render object directly */ + render(renderer: IRenderer): void; +} + +/** + * Interface for Container to interface with Renderer. + * @memberof PIXI + */ +export interface IRenderableContainer extends IRenderableObject +{ + /** Get Local bounds for container */ + getLocalBounds(rect?: Rectangle, skipChildrenUpdate?: boolean): Rectangle; +} + +/** Mixed WebGL1/WebGL2 Rendering Context. Either its WebGL2, either its WebGL1 with PixiJS polyfills on it */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IRenderingContext extends WebGL2RenderingContext +{ + +} + +export interface IRendererOptions extends GlobalMixins.IRendererOptions +{ + width?: number; + height?: number; + view?: HTMLCanvasElement; + /** + * Use premultipliedAlpha and backgroundAlpha instead + * @deprecated since 7.0.0 + */ + useContextAlpha?: boolean | 'notMultiplied'; + autoDensity?: boolean; + antialias?: boolean; + resolution?: number; + preserveDrawingBuffer?: boolean; + clearBeforeRender?: boolean; + backgroundColor?: number; + backgroundAlpha?: number; + premultipliedAlpha?: boolean; + powerPreference?: WebGLPowerPreference; + context?: IRenderingContext; +} + +export interface IRendererRenderOptions +{ + renderTexture?: RenderTexture; + blit?: boolean + clear?: boolean; + transform?: Matrix; + skipUpdateTransform?: boolean; +} + +/** + * Starard Interface for a Pixi renderer. + * @memberof PIXI + */ +export interface IRenderer extends SystemManager, GlobalMixins.IRenderer +{ + + resize(width: number, height: number): void; + render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void + generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): void + destroy(removeView?: boolean): void; + clear(): void; + reset(): void; + + /** + * The type of the renderer. + * @see PIXI.RENDERER_TYPE + */ + readonly type: RENDERER_TYPE + + /** When logging Pixi to the console, this is the name we will show */ + readonly rendererLogId: string + + /** The canvas element that everything is drawn to.*/ + readonly view: HTMLCanvasElement + /** Flag if we are rendering to the screen vs renderTexture */ + readonly renderingToScreen: boolean + /** The resolution / device pixel ratio of the renderer. */ + readonly resolution: number + /** the width of the screen */ + readonly width: number + /** the height of the screen */ + readonly height: number + /** + * Measurements of the screen. (0, 0, screenWidth, screenHeight). + * Its safe to use as filterArea or hitArea for the whole stage. + */ + readonly screen: Rectangle + /** the last object rendered by the renderer. Useful for other plugins like interaction managers */ + readonly lastObjectRendered: IRenderableObject + /** Collection of plugins */ + readonly plugins: IRendererPlugins +} diff --git a/packages/core/src/IRenderingContext.ts b/packages/core/src/IRenderingContext.ts deleted file mode 100644 index de2b9f29246..00000000000 --- a/packages/core/src/IRenderingContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Mixed WebGL1/WebGL2 Rendering Context. - * Either its WebGL2, either its WebGL1 with PixiJS polyfills on it - */ -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface IRenderingContext extends WebGL2RenderingContext -{ - -} diff --git a/packages/core/src/ISystem.ts b/packages/core/src/ISystem.ts deleted file mode 100644 index 9c4a147c9d7..00000000000 --- a/packages/core/src/ISystem.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { Renderer } from './Renderer'; -import { deprecation } from '@pixi/utils'; - -/** - * Interface for systems used by the {@link PIXI.Renderer}. - * @memberof PIXI - */ -export interface ISystem -{ - /** - * Generic destroy methods to be overridden by the subclass - */ - destroy(): void; -} - -/** - * Types for system and pipe classes. - * - * @ignore - */ -export interface ISystemConstructor -{ - new (renderer: R): ISystem; -} - -/** - * Use the ISystem interface instead. - * @deprecated since 6.1.0 - * @memberof PIXI - */ -export class System implements ISystem -{ - /** Reference to the main renderer */ - public renderer: Renderer; - - /** - * @param renderer - Reference to Renderer - */ - constructor(renderer: Renderer) - { - // #if _DEBUG - deprecation('6.1.0', 'System class is deprecated, implemement ISystem interface instead.'); - // #endif - - this.renderer = renderer; - } - - /** Destroy and don't use after this. */ - destroy(): void - { - this.renderer = null; - } -} diff --git a/packages/core/src/Renderer.ts b/packages/core/src/Renderer.ts index 19ba626c73f..6d5fbe1aa5d 100644 --- a/packages/core/src/Renderer.ts +++ b/packages/core/src/Renderer.ts @@ -1,47 +1,49 @@ -import { AbstractRenderer } from './AbstractRenderer'; -import { sayHello, isWebGLSupported, deprecation } from '@pixi/utils'; -import { MaskSystem } from './mask/MaskSystem'; -import { StencilSystem } from './mask/StencilSystem'; -import { ScissorSystem } from './mask/ScissorSystem'; -import { FilterSystem } from './filters/FilterSystem'; -import { FramebufferSystem } from './framebuffer/FramebufferSystem'; -import { RenderTextureSystem } from './renderTexture/RenderTextureSystem'; -import { TextureSystem } from './textures/TextureSystem'; -import { ProjectionSystem } from './projection/ProjectionSystem'; -import { StateSystem } from './state/StateSystem'; -import { GeometrySystem } from './geometry/GeometrySystem'; -import { ShaderSystem } from './shader/ShaderSystem'; -import { ContextSystem } from './context/ContextSystem'; -import { BatchSystem } from './batch/BatchSystem'; -import { TextureGCSystem } from './textures/TextureGCSystem'; -import { MSAA_QUALITY, RENDERER_TYPE } from '@pixi/constants'; +import { isWebGLSupported, deprecation } from '@pixi/utils'; +import type { MaskSystem } from './mask/MaskSystem'; +import type { StencilSystem } from './mask/StencilSystem'; +import type { ScissorSystem } from './mask/ScissorSystem'; +import type { FilterSystem } from './filters/FilterSystem'; +import type { FramebufferSystem } from './framebuffer/FramebufferSystem'; +import type { RenderTextureSystem } from './renderTexture/RenderTextureSystem'; +import type { TextureSystem } from './textures/TextureSystem'; +import type { ProjectionSystem } from './projection/ProjectionSystem'; +import type { StateSystem } from './state/StateSystem'; +import type { GeometrySystem } from './geometry/GeometrySystem'; +import type { ShaderSystem } from './shader/ShaderSystem'; +import type { ContextSystem } from './context/ContextSystem'; +import type { BatchSystem } from './batch/BatchSystem'; +import type { TextureGCSystem } from './textures/TextureGCSystem'; +import type { MSAA_QUALITY, RENDERER_TYPE } from '@pixi/constants'; import { UniformGroup } from './shader/UniformGroup'; -import { Matrix, Rectangle } from '@pixi/math'; -import { Runner } from '@pixi/runner'; -import { BufferSystem } from './geometry/BufferSystem'; -import { RenderTexture } from './renderTexture/RenderTexture'; - -import type { SCALE_MODES } from '@pixi/constants'; -import type { IRendererOptions, IRendererPlugins, IRendererRenderOptions, - IGenerateTextureOptions } from './AbstractRenderer'; -import type { ISystemConstructor } from './ISystem'; -import type { IRenderingContext } from './IRenderingContext'; -import type { IRenderableObject } from './IRenderableObject'; - -export interface IRendererPluginConstructor { - new (renderer: Renderer, options?: any): IRendererPlugin; -} - -export interface IRendererPlugin { - destroy(): void; -} +import type { Rectangle } from '@pixi/math'; +import { Matrix } from '@pixi/math'; +import type { BufferSystem } from './geometry/BufferSystem'; +import type { RenderTexture } from './renderTexture/RenderTexture'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { PluginSystem, IRendererPlugins } from './plugin/PluginSystem'; +import type { MultisampleSystem } from './framebuffer/MultisampleSystem'; +import type { IGenerateTextureOptions, GenerateTextureSystem } from './renderTexture/GenerateTextureSystem'; +import type { BackgroundSystem } from './background/BackgroundSystem'; +import type { ViewSystem } from './view/ViewSystem'; +import type { ObjectRendererSystem } from './render/ObjectRendererSystem'; +import { settings } from '@pixi/settings'; +import { SystemManager } from './system/SystemManager'; +import type { IRenderableObject, IRenderer, IRendererOptions, IRendererRenderOptions, IRenderingContext } from './IRenderer'; +import type { StartupSystem, StartupOptions } from './startup/StartupSystem'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Renderer extends GlobalMixins.Renderer {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Renderer extends GlobalMixins.Renderer {} /** * The Renderer draws the scene and all its content onto a WebGL enabled canvas. * * This renderer should be used for browsers that support WebGL. * - * This renderer works by automatically managing WebGLBatchesm, so no need for Sprite Batches or Sprite Clouds. + * This renderer works by automatically managing WebGLBatches, so no need for Sprite Batches or Sprite Clouds. * Don't forget to add the view to your DOM or you will not see anything! * * Renderer is composed of systems that manage specific tasks. The following systems are added by default @@ -49,180 +51,226 @@ export interface IRendererPlugin { * * | System | Description | * | ------------------------------------ | ----------------------------------------------------------------------------- | - * | {@link PIXI.BatchSystem} | This manages object renderers that defer rendering until a flush. | - * | {@link PIXI.ContextSystem} | This manages the WebGL context and extensions. | + * + * | Generic Systems | Systems that manage functionality that all renderer types share | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * | {@link PIXI.ViewSystem} | This manages the main view of the renderer usually a Canvas | + * | {@link PIXI.PluginSystem} | This manages plugins for the renderer | + * | {@link PIXI.BackgroundSystem} | This manages the main views background color and alpha | + * | {@link PIXI.StartupSystem} | Boots up a renderer and initiatives all the systems | * | {@link PIXI.EventSystem} | This manages UI events. | - * | {@link PIXI.FilterSystem} | This manages the filtering pipeline for post-processing effects. | + * + * | WebGL Core Systems | Provide an optimised, easy to use API to work with WebGL | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * | {@link PIXI.ContextSystem} | This manages the WebGL context and extensions. | * | {@link PIXI.FramebufferSystem} | This manages framebuffers, which are used for offscreen rendering. | * | {@link PIXI.GeometrySystem} | This manages geometries & buffers, which are used to draw object meshes. | - * | {@link PIXI.MaskSystem} | This manages masking operations. | - * | {@link PIXI.ProjectionSystem} | This manages the `projectionMatrix`, used by shaders to get NDC coordinates. | - * | {@link PIXI.RenderTextureSystem} | This manages render-textures, which are an abstraction over framebuffers. | - * | {@link PIXI.ScissorSystem} | This handles scissor masking, and is used internally by {@link MaskSystem} | * | {@link PIXI.ShaderSystem} | This manages shaders, programs that run on the GPU to calculate 'em pixels. | * | {@link PIXI.StateSystem} | This manages the WebGL state variables like blend mode, depth testing, etc. | - * | {@link PIXI.StencilSystem} | This handles stencil masking, and is used internally by {@link MaskSystem} | * | {@link PIXI.TextureSystem} | This manages textures and their resources on the GPU. | * | {@link PIXI.TextureGCSystem} | This will automatically remove textures from the GPU if they are not used. | + * | {@link PIXI.MultisampleSystem} | This manages the multisample const on the WEbGL Renderer | * - * The breadth of the API surface provided by the renderer is contained within these systems. + * | PixiJS High-Level Systems | Set of specific systems designed to work with PixiJS objects | + * | ------------------------------------ | ----------------------------------------------------------------------------- | + * | {@link PIXI.RenderSystem} | This adds the ability to render a PIXI.DisplayObject | + * | {@link PIXI.GenerateTextureSystem} | This adds the ability to generate textures from any PIXI.DisplayObject | + * | {@link PIXI.ProjectionSystem} | This manages the `projectionMatrix`, used by shaders to get NDC coordinates. | + * | {@link PIXI.RenderTextureSystem} | This manages render-textures, which are an abstraction over framebuffers. | + * | {@link PIXI.MaskSystem} | This manages masking operations. | + * | {@link PIXI.ScissorSystem} | This handles scissor masking, and is used internally by {@link MaskSystem} | + * | {@link PIXI.StencilSystem} | This handles stencil masking, and is used internally by {@link MaskSystem} | + * | {@link PIXI.FilterSystem} | This manages the filtering pipeline for post-processing effects. | + * | {@link PIXI.BatchSystem} | This manages object renderers that defer rendering until a flush. | + * | {@link PIXI.Prepare} | This manages uploading assets to the GPU. | + * | {@link PIXI.Extract} | This extracts image data from display objects. | * + * The breadth of the API surface provided by the renderer is contained within these systems. * @memberof PIXI */ -export class Renderer extends AbstractRenderer +export class Renderer extends SystemManager implements IRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.Renderer, + priority: 1, + }; + + /** + * The type of the renderer. will be PIXI.RENDERER_TYPE.CANVAS + * @member {number} + * @see PIXI.RENDERER_TYPE + */ + public readonly type: RENDERER_TYPE.WEBGL; + /** * WebGL context, set by {@link PIXI.ContextSystem this.context}. - * * @readonly * @member {WebGLRenderingContext} */ public gl: IRenderingContext; - /** Global uniforms */ + /** + * Global uniforms + * Add any uniforms you want shared across your shaders. + * the must be added before the scene is rendered for the first time + * as we dynamically buildcode to handle all global var per shader + * + */ public globalUniforms: UniformGroup; /** Unique UID assigned to the renderer's WebGL context. */ public CONTEXT_UID: number; - /** - * Flag if we are rendering to the screen vs renderTexture - * - * @readonly - * @default true - */ - public renderingToScreen: boolean; - - /** - * The number of msaa samples of the canvas. - * @readonly - */ - public multisample: MSAA_QUALITY; // systems /** * Mask system instance * @readonly */ - public mask: MaskSystem; + public readonly mask: MaskSystem; /** * Context system instance * @readonly */ - public context: ContextSystem; + public readonly context: ContextSystem; /** * State system instance * @readonly */ - public state: StateSystem; + public readonly state: StateSystem; /** * Shader system instance * @readonly */ - public shader: ShaderSystem; + public readonly shader: ShaderSystem; /** * Texture system instance * @readonly */ - public texture: TextureSystem; + public readonly texture: TextureSystem; /** * Buffer system instance * @readonly */ - public buffer: BufferSystem; + public readonly buffer: BufferSystem; /** * Geometry system instance * @readonly */ - public geometry: GeometrySystem; + public readonly geometry: GeometrySystem; /** * Framebuffer system instance * @readonly */ - public framebuffer: FramebufferSystem; + public readonly framebuffer: FramebufferSystem; /** * Scissor system instance * @readonly */ - public scissor: ScissorSystem; + public readonly scissor: ScissorSystem; /** * Stencil system instance * @readonly */ - public stencil: StencilSystem; + public readonly stencil: StencilSystem; /** * Projection system instance * @readonly */ - public projection: ProjectionSystem; + public readonly projection: ProjectionSystem; /** * Texture garbage collector system instance * @readonly */ - public textureGC: TextureGCSystem; + public readonly textureGC: TextureGCSystem; /** * Filter system instance * @readonly */ - public filter: FilterSystem; + public readonly filter: FilterSystem; /** * RenderTexture system instance * @readonly */ - public renderTexture: RenderTextureSystem; + public readonly renderTexture: RenderTextureSystem; /** * Batch system instance * @readonly */ - public batch: BatchSystem; + public readonly batch: BatchSystem; /** - * Internal signal instances of **runner**, these - * are assigned to each system created. - * @see PIXI.Runner - * @name runners - * @private - * @type {object} + * plugin system instance + * @readonly + */ + public readonly _plugin: PluginSystem; + + /** + * _multisample system instance + * @readonly + */ + public readonly _multisample: MultisampleSystem; + + /** + * textureGenerator system instance + * @readonly + */ + public readonly textureGenerator: GenerateTextureSystem; + + /** + * background system instance + * @readonly + */ + public readonly background: BackgroundSystem; + + /** + * _view system instance + * @readonly + */ + public readonly _view: ViewSystem; + + /** + * _render system instance + * @readonly + */ + public readonly objectRenderer: ObjectRendererSystem; + + /** + * startup system instance * @readonly - * @property {PIXI.Runner} destroy - Destroy runner - * @property {PIXI.Runner} contextChange - Context change runner - * @property {PIXI.Runner} reset - Reset runner - * @property {PIXI.Runner} update - Update runner - * @property {PIXI.Runner} postrender - Post-render runner - * @property {PIXI.Runner} prerender - Pre-render runner - * @property {PIXI.Runner} resize - Resize runner */ - runners: {[key: string]: Runner}; + public readonly startup: StartupSystem; /** * Create renderer if WebGL is available. Overrideable * by the **@pixi/canvas-renderer** package to allow fallback. * throws error if WebGL is not available. - * + * @param options * @private */ - static create(options?: IRendererOptions): AbstractRenderer + static test(options?: IRendererOptions): boolean { - if (isWebGLSupported()) + if (options?.forceCanvas) { - return new Renderer(options); + return false; } - throw new Error('WebGL unsupported in this browser, use "pixi.js-legacy" for fallback canvas2d support.'); + return isWebGLSupported(); } /** @@ -249,176 +297,86 @@ export class Renderer extends AbstractRenderer * @param {string} [options.powerPreference] - Parameter passed to WebGL context, set to "high-performance" * for devices with dual graphics card. * @param {object} [options.context] - If WebGL context already exists, all parameters must be taken from it. + * @param {object} [options.blit] - if rendering to a renderTexture, set to true if you want to run blit after + * the render. defaults to false. */ - constructor(options? : IRendererOptions) + constructor(options?: IRendererOptions) { - super(RENDERER_TYPE.WEBGL, options); + super(); - // the options will have been modified here in the super constructor with pixi's default settings.. - options = this.options; + // Add the default render options + options = Object.assign({}, settings.RENDER_OPTIONS, options); this.gl = null; this.CONTEXT_UID = 0; - this.runners = { - destroy: new Runner('destroy'), - contextChange: new Runner('contextChange'), - reset: new Runner('reset'), - update: new Runner('update'), - postrender: new Runner('postrender'), - prerender: new Runner('prerender'), - resize: new Runner('resize'), - }; - - this.runners.contextChange.add(this); - this.globalUniforms = new UniformGroup({ projectionMatrix: new Matrix(), }, true); - this.addSystem(MaskSystem, 'mask') - .addSystem(ContextSystem, 'context') - .addSystem(StateSystem, 'state') - .addSystem(ShaderSystem, 'shader') - .addSystem(TextureSystem, 'texture') - .addSystem(BufferSystem, 'buffer') - .addSystem(GeometrySystem, 'geometry') - .addSystem(FramebufferSystem, 'framebuffer') - .addSystem(ScissorSystem, 'scissor') - .addSystem(StencilSystem, 'stencil') - .addSystem(ProjectionSystem, 'projection') - .addSystem(TextureGCSystem, 'textureGC') - .addSystem(FilterSystem, 'filter') - .addSystem(RenderTextureSystem, 'renderTexture') - .addSystem(BatchSystem, 'batch'); - - this.initPlugins(Renderer.__plugins); - - this.multisample = undefined; - - /* - * The options passed in to create a new WebGL context. - */ - if (options.context) - { - this.context.initFromContext(options.context); - } - else - { - this.context.initFromOptions({ - alpha: !!this.useContextAlpha, + const systemConfig = { + runners: ['init', 'destroy', 'contextChange', 'reset', 'update', 'postrender', 'prerender', 'resize'], + systems: Renderer.__systems, + priority: [ + '_view', + 'textureGenerator', + 'background', + '_plugin', + 'startup', + // low level WebGL systems + 'context', + 'state', + 'texture', + 'buffer', + 'geometry', + 'framebuffer', + // high level pixi specific rendering + 'mask', + 'scissor', + 'stencil', + 'projection', + 'textureGC', + 'filter', + 'renderTexture', + 'batch', + 'objectRenderer', + '_multisample' + ], + }; + + this.setup(systemConfig); + + // new options! + const startupOptions: StartupOptions = { + _plugin: Renderer.__plugins, + background: { + alpha: options.backgroundAlpha, + color: options.backgroundColor, + clearBeforeRender: options.clearBeforeRender, + }, + _view: { + height: options.height, + width: options.width, + autoDensity: options.autoDensity, + resolution: options.resolution, + view: options.view, + }, + context: { antialias: options.antialias, - premultipliedAlpha: this.useContextAlpha && this.useContextAlpha !== 'notMultiplied', - stencil: true, + context: options.context, + powerPreference: options.powerPreference, + premultipliedAlpha: options.premultipliedAlpha + ?? (options.useContextAlpha && options.useContextAlpha !== 'notMultiplied'), preserveDrawingBuffer: options.preserveDrawingBuffer, - powerPreference: this.options.powerPreference, - }); - } - - this.renderingToScreen = true; - - sayHello(this.context.webGLVersion === 2 ? 'WebGL 2' : 'WebGL 1'); - - this.resize(this.options.width, this.options.height); - } - - protected contextChange(): void - { - const gl = this.gl; - - let samples; - - if (this.context.webGLVersion === 1) - { - const framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - samples = gl.getParameter(gl.SAMPLES); - - gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); - } - else - { - const framebuffer = gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING); - - gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); - - samples = gl.getParameter(gl.SAMPLES); - - gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer); - } - - if (samples >= MSAA_QUALITY.HIGH) - { - this.multisample = MSAA_QUALITY.HIGH; - } - else if (samples >= MSAA_QUALITY.MEDIUM) - { - this.multisample = MSAA_QUALITY.MEDIUM; - } - else if (samples >= MSAA_QUALITY.LOW) - { - this.multisample = MSAA_QUALITY.LOW; - } - else - { - this.multisample = MSAA_QUALITY.NONE; - } - } - - /** - * Add a new system to the renderer. - * - * @param ClassRef - Class reference - * @param name - Property name for system, if not specified - * will use a static `name` property on the class itself. This - * name will be assigned as s property on the Renderer so make - * sure it doesn't collide with properties on Renderer. - * @return Return instance of renderer - */ - addSystem(ClassRef: ISystemConstructor, name: string): this - { - const system = new ClassRef(this); - - if ((this as any)[name]) - { - throw new Error(`Whoops! The name "${name}" is already in use`); - } - - (this as any)[name] = system; - - for (const i in this.runners) - { - this.runners[i].add(system); - } - - /** - * Fired after rendering finishes. - * - * @event PIXI.Renderer#postrender - */ - - /** - * Fired before rendering starts. - * - * @event PIXI.Renderer#prerender - */ - - /** - * Fired when the WebGL context is set. - * - * @event PIXI.Renderer#context - * @param {WebGLRenderingContext} gl - WebGL context. - */ + }, + }; - return this; + this.startup.run(startupOptions); } /** * Renders the object to its WebGL view. - * * @param displayObject - The object to be rendered. * @param {object} [options] - Object to use for render options. * @param {PIXI.RenderTexture} [options.renderTexture] - The render texture to render to. @@ -426,220 +384,277 @@ export class Renderer extends AbstractRenderer * @param {PIXI.Matrix} [options.transform] - A transform to apply to the render texture before rendering. * @param {boolean} [options.skipUpdateTransform=false] - Should we skip the update transform pass? */ - render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void; + render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void + { + this.objectRenderer.render(displayObject, options); + } /** - * Please use the `option` render arguments instead. - * - * @deprecated Since 6.0.0 - * @param displayObject - * @param renderTexture - * @param clear - * @param transform - * @param skipUpdateTransform + * Resizes the WebGL view to the specified width and height. + * @param desiredScreenWidth - The desired width of the screen. + * @param desiredScreenHeight - The desired height of the screen. */ - render(displayObject: IRenderableObject, renderTexture?: RenderTexture, - clear?: boolean, transform?: Matrix, skipUpdateTransform?: boolean): void; + resize(desiredScreenWidth: number, desiredScreenHeight: number): void + { + this._view.resizeView(desiredScreenWidth, desiredScreenHeight); + } /** - * @ignore + * Resets the WebGL state so you can render things however you fancy! + * @returns Returns itself. */ - render(displayObject: IRenderableObject, options?: IRendererRenderOptions | RenderTexture): void + reset(): this { - let renderTexture: RenderTexture; - let clear: boolean; - let transform: Matrix; - let skipUpdateTransform: boolean; + this.runners.reset.emit(); - if (options) - { - if (options instanceof RenderTexture) - { - // #if _DEBUG - deprecation('6.0.0', 'Renderer#render arguments changed, use options instead.'); - // #endif - - /* eslint-disable prefer-rest-params */ - renderTexture = options; - clear = arguments[2]; - transform = arguments[3]; - skipUpdateTransform = arguments[4]; - /* eslint-enable prefer-rest-params */ - } - else - { - renderTexture = options.renderTexture; - clear = options.clear; - transform = options.transform; - skipUpdateTransform = options.skipUpdateTransform; - } - } + return this; + } - // can be handy to know! - this.renderingToScreen = !renderTexture; + /** Clear the frame buffer. */ + clear(): void + { + this.renderTexture.bind(); + this.renderTexture.clear(); + } - this.runners.prerender.emit(); - this.emit('prerender'); + /** + * Removes everything from the renderer (event listeners, spritebatch, etc...) + * @param [removeView=false] - Removes the Canvas element from the DOM. + * See: https://github.com/pixijs/pixi.js/issues/2233 + */ + destroy(removeView = false): void + { + this.runners.destroy.items.reverse(); - // apply a transform at a GPU level - this.projection.transform = transform; + this.emitWithCustomOptions(this.runners.destroy, { + _view: removeView, + }); - // no point rendering if our context has been blown up! - if (this.context.isLost) - { - return; - } + super.destroy(); + } - if (!renderTexture) - { - this._lastObjectRendered = displayObject; - } + /** Collection of plugins */ + get plugins(): IRendererPlugins + { + return this._plugin.plugins; + } - if (!skipUpdateTransform) - { - // update the scene graph - const cacheParent = displayObject.enableTempParent(); + /** The number of msaa samples of the canvas. */ + get multisample(): MSAA_QUALITY + { + return this._multisample.multisample; + } - displayObject.updateTransform(); - displayObject.disableTempParent(cacheParent); - // displayObject.hitArea = //TODO add a temp hit area - } + /** + * Same as view.width, actual number of pixels in the canvas by horizontal. + * @member {number} + * @readonly + * @default 800 + */ + get width(): number + { + return this._view.element.width; + } - this.renderTexture.bind(renderTexture); - this.batch.currentRenderer.start(); + /** + * Same as view.height, actual number of pixels in the canvas by vertical. + * @default 600 + */ + get height(): number + { + return this._view.element.height; + } - if (clear !== undefined ? clear : this.clearBeforeRender) - { - this.renderTexture.clear(); - } + /** The resolution / device pixel ratio of the renderer. */ + get resolution(): number + { + return this._view.resolution; + } - displayObject.render(this); + /** Whether CSS dimensions of canvas view should be resized to screen dimensions automatically. */ + get autoDensity(): boolean + { + return this._view.autoDensity; + } - // apply transform.. - this.batch.currentRenderer.flush(); + /** The canvas element that everything is drawn to.*/ + get view(): HTMLCanvasElement + { + return this._view.element; + } - if (renderTexture) - { - renderTexture.baseTexture.update(); - } + /** + * Measurements of the screen. (0, 0, screenWidth, screenHeight). + * + * Its safe to use as filterArea or hitArea for the whole stage. + * @member {PIXI.Rectangle} + */ + get screen(): Rectangle + { + return this._view.screen; + } - this.runners.postrender.emit(); + /** the last object rendered by the renderer. Useful for other plugins like interaction managers */ + get lastObjectRendered(): IRenderableObject + { + return this.objectRenderer.lastObjectRendered; + } - // reset transform after render - this.projection.transform = null; + /** Flag if we are rendering to the screen vs renderTexture */ + get renderingToScreen(): boolean + { + return this.objectRenderer.renderingToScreen; + } - this.emit('postrender'); + /** When logging Pixi to the console, this is the name we will show */ + get rendererLogId(): string + { + return `WebGL ${this.context.webGLVersion}`; } /** - * @override - * @ignore + * This sets weather the screen is totally cleared between each frame withthe background color and alpha + * @deprecated since 7.0.0 */ - generateTexture(displayObject: IRenderableObject, - options: IGenerateTextureOptions | SCALE_MODES = {}, - resolution?: number, region?: Rectangle): RenderTexture + get clearBeforeRender(): boolean { - const renderTexture = super.generateTexture(displayObject, options as any, resolution, region); + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.useContextAlpha has been deprecated, please use renderer.background.clearBeforeRender instead.'); + // #endif - this.framebuffer.blit(); + return this.background.clearBeforeRender; + } + + /** + * Pass-thru setting for the canvas' context `alpha` property. This is typically + * not something you need to fiddle with. If you want transparency, use `backgroundAlpha`. + * @deprecated since 7.0.0 + * @member {boolean} + */ + get useContextAlpha(): boolean | 'notMultiplied' + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'Renderer#useContextAlpha has been deprecated, please use Renderer#context.premultipliedAlpha instead.'); + // #endif - return renderTexture; + return this.context.useContextAlpha; } /** - * Resizes the WebGL view to the specified width and height. - * - * @param desiredScreenWidth - The desired width of the screen. - * @param desiredScreenHeight - The desired height of the screen. + * readonly drawing buffer preservation + * we can only know this if Pixi created the context + * @deprecated since 7.0.0 */ - resize(desiredScreenWidth: number, desiredScreenHeight: number): void + get preserveDrawingBuffer(): boolean { - super.resize(desiredScreenWidth, desiredScreenHeight); + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.preserveDrawingBuffer has been deprecated, we cannot truly know this unless pixi created the context'); + // #endif - this.runners.resize.emit(this.screen.height, this.screen.width); + return this.context.preserveDrawingBuffer; } /** - * Resets the WebGL state so you can render things however you fancy! - * - * @return Returns itself. + * The background color to fill if not transparent + * @member {number} + * @deprecated since 7.0.0 */ - reset(): this + get backgroundColor(): number { - this.runners.reset.emit(); + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundColor has been deprecated, use renderer.background.color instead.'); + // #endif - return this; + return this.background.color; } - /** Clear the frame buffer. */ - clear(): void + set backgroundColor(value: number) { - this.renderTexture.bind(); - this.renderTexture.clear(); + // #if _DEBUG + deprecation('7.0.0', 'renderer.backgroundColor has been deprecated, use renderer.background.color instead.'); + // #endif + + this.background.color = value; } /** - * Removes everything from the renderer (event listeners, spritebatch, etc...) - * - * @param [removeView=false] - Removes the Canvas element from the DOM. - * See: https://github.com/pixijs/pixi.js/issues/2233 + * The background color alpha. Setting this to 0 will make the canvas transparent. + * @member {number} + * @deprecated since 7.0.0 */ - destroy(removeView?: boolean): void + get backgroundAlpha(): number { - this.runners.destroy.emit(); + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundAlpha has been deprecated, use renderer.background.alpha instead.'); + // #endif - for (const r in this.runners) - { - this.runners[r].destroy(); - } + return this.background.color; + } - // call base destroy - super.destroy(removeView); + /** + * @deprecated since 7.0.0 + */ + set backgroundAlpha(value: number) + { + // #if _DEBUG + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.backgroundAlpha has been deprecated, use renderer.background.alpha instead.'); + // #endif - // TODO nullify all the managers.. - this.gl = null; + this.background.alpha = value; } /** - * Please use `plugins.extract` instead. - * @member {PIXI.Extract} extract - * @deprecated since 6.0.0 - * @readonly + * @deprecated since 7.0.0 */ - public get extract(): any + get powerPreference(): WebGLPowerPreference { // #if _DEBUG - deprecation('6.0.0', 'Renderer#extract has been deprecated, please use Renderer#plugins.extract instead.'); + // eslint-disable-next-line max-len + deprecation('7.0.0', 'renderer.powerPreference has been deprecated, we can only know this if pixi creates the context'); // #endif - return this.plugins.extract; + return this.context.powerPreference; + } + + /** + * Useful function that returns a texture of the display object that can then be used to create sprites + * This can be quite useful if your displayObject is complicated and needs to be reused multiple times. + * @param displayObject - The displayObject the object will be generated from. + * @param {object} options - Generate texture options. + * @param {PIXI.SCALE_MODES} options.scaleMode - The scale mode of the texture. + * @param {number} options.resolution - The resolution / device pixel ratio of the texture being generated. + * @param {PIXI.Rectangle} options.region - The region of the displayObject, that shall be rendered, + * if no region is specified, defaults to the local bounds of the displayObject. + * @param {PIXI.MSAA_QUALITY} options.multisample - The number of samples of the frame buffer. + * @returns A texture of the graphics object. + */ + generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): RenderTexture + { + return this.textureGenerator.generateTexture(displayObject, options); } /** * Collection of installed plugins. These are included by default in PIXI, but can be excluded * by creating a custom build. Consult the README for more information about creating custom * builds and excluding plugins. - * - * @readonly - * @property {PIXI.AccessibilityManager} accessibility Support tabbing interactive elements. - * @property {PIXI.Extract} extract Extract image data from renderer. - * @property {PIXI.InteractionManager} interaction Handles mouse, touch and pointer events. - * @property {PIXI.ParticleRenderer} particle Renderer for ParticleContainer objects. - * @property {PIXI.Prepare} prepare Pre-render display objects. - * @property {PIXI.BatchRenderer} batch Batching of Sprite, Graphics and Mesh objects. - * @property {PIXI.TilingSpriteRenderer} tilingSprite Renderer for TilingSprite objects. + * @private */ - static __plugins: IRendererPlugins; + static readonly __plugins: IRendererPlugins = {}; /** - * Adds a plugin to the renderer. - * - * @param pluginName - The name of the plugin. - * @param ctor - The constructor function or class for the plugin. + * The collection of installed systems. + * @private */ - static registerPlugin(pluginName: string, ctor: IRendererPluginConstructor): void - { - Renderer.__plugins = Renderer.__plugins || {}; - Renderer.__plugins[pluginName] = ctor; - } + static readonly __systems: Record = {}; } + +// Handle registration of extensions +extensions.handleByMap(ExtensionType.RendererPlugin, Renderer.__plugins); +extensions.handleByMap(ExtensionType.RendererSystem, Renderer.__systems); +extensions.add(Renderer); diff --git a/packages/core/src/autoDetectRenderer.ts b/packages/core/src/autoDetectRenderer.ts index c89b685a9c0..65144a261a4 100644 --- a/packages/core/src/autoDetectRenderer.ts +++ b/packages/core/src/autoDetectRenderer.ts @@ -1,15 +1,29 @@ -import { Renderer } from './Renderer'; -import type { AbstractRenderer, IRendererOptions } from './AbstractRenderer'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { IRenderer, IRendererOptions } from './IRenderer'; export interface IRendererOptionsAuto extends IRendererOptions { forceCanvas?: boolean; } + +export interface IRendererConstructor +{ + test(options?: IRendererOptionsAuto): boolean; + new (options?: IRendererOptionsAuto): IRenderer; +} + +/** + * Collection of installed Renderers. + * @ignore + */ +const renderers: IRendererConstructor[] = []; + +extensions.handleByList(ExtensionType.Renderer, renderers); + /** * This helper function will automatically detect which renderer you should be using. * WebGL is the preferred renderer as it is a lot faster. If WebGL is not supported by * the browser then this function will return a canvas renderer - * * @memberof PIXI * @function autoDetectRenderer * @param {object} [options] - The optional renderer parameters @@ -35,9 +49,17 @@ export interface IRendererOptionsAuto extends IRendererOptions * it is ignored. * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" * for devices with dual graphics card **webgl only** - * @return {PIXI.Renderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer + * @returns {PIXI.Renderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ -export function autoDetectRenderer(options?: IRendererOptionsAuto): AbstractRenderer +export function autoDetectRenderer(options?: IRendererOptionsAuto): IRenderer { - return Renderer.create(options); + for (const RendererType of renderers) + { + if (RendererType.test(options)) + { + return new RendererType(options); + } + } + + throw new Error('Unable to auto-detect a suitable renderer.'); } diff --git a/packages/core/src/background/BackgroundSystem.ts b/packages/core/src/background/BackgroundSystem.ts new file mode 100644 index 00000000000..d510be93172 --- /dev/null +++ b/packages/core/src/background/BackgroundSystem.ts @@ -0,0 +1,127 @@ +import { hex2rgb, hex2string } from '@pixi/utils'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { ISystem } from '../system/ISystem'; + +export interface BackgroundOptions +{ + /** the main canvas background alpha. From 0 (fully transparent) to 1 (fully opaque). */ + alpha: number, + /** the main canvas background color. */ + color: number, + /** sets if the renderer will clear the canvas or not before the new render pass. */ + clearBeforeRender: boolean, +} + +/** + * The background system manages the background color and alpha of the main view. + * @memberof PIXI + */ +export class BackgroundSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + name: 'background', + }; + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent PixiJS will use a canvas sized fillRect operation every + * frame to set the canvas background color. If the scene is transparent PixiJS will use clearRect + * to clear the canvas every frame. Disable this by setting this to false. For example, if + * your game has a canvas filling background image you often don't need this set. + * @member {boolean} + * @default + */ + public clearBeforeRender: boolean; + + private _backgroundColorString: string; + private _backgroundColorRgba: number[]; + private _backgroundColor: number; + + constructor() + { + this.clearBeforeRender = true; + + this._backgroundColor = 0x000000; + + this._backgroundColorRgba = [0, 0, 0, 1]; + + this._backgroundColorString = '#000000'; + + this.color = this._backgroundColor; // run bg color setter + this.alpha = 1; + } + + /** + * initiates the background system + * @param {BackgroundOptions} options - the options for the background colors + */ + init(options: BackgroundOptions): void + { + this.clearBeforeRender = options.clearBeforeRender; + this.color = options.color || this._backgroundColor; // run bg color setter + this.alpha = options.alpha; + } + + /** + * The background color to fill if not transparent + * @member {number} + */ + get color(): number + { + return this._backgroundColor; + } + + set color(value: number) + { + this._backgroundColor = value; + this._backgroundColorString = hex2string(value); + hex2rgb(value, this._backgroundColorRgba); + } + + /** + * The background color alpha. Setting this to 0 will make the canvas transparent. + * @member {number} + */ + get alpha(): number + { + return this._backgroundColorRgba[3]; + } + + set alpha(value: number) + { + this._backgroundColorRgba[3] = value; + } + + /** + * The background color as an [R, G, B, A] array. + * @member {number[]} + * @protected + */ + get colorRgba(): number[] + { + return this._backgroundColorRgba; + } + + /** + * The background color as a string. + * @member {string} + * @protected + */ + get colorString(): string + { + return this._backgroundColorString; + } + + destroy(): void + { + // ka boom! + } +} + +extensions.add(BackgroundSystem); diff --git a/packages/core/src/batch/BatchDrawCall.ts b/packages/core/src/batch/BatchDrawCall.ts index 69020864903..f3fade5b1a8 100644 --- a/packages/core/src/batch/BatchDrawCall.ts +++ b/packages/core/src/batch/BatchDrawCall.ts @@ -6,7 +6,6 @@ import type { BatchTextureArray } from './BatchTextureArray'; /** * Used by the batcher to draw batches. * Each one of these contains all information required to draw a bound geometry. - * * @memberof PIXI */ export class BatchDrawCall diff --git a/packages/core/src/batch/BatchGeometry.ts b/packages/core/src/batch/BatchGeometry.ts index 9d48cba1c71..98419bd4b19 100644 --- a/packages/core/src/batch/BatchGeometry.ts +++ b/packages/core/src/batch/BatchGeometry.ts @@ -4,21 +4,18 @@ import { Buffer } from '../geometry/Buffer'; /** * Geometry used to batch standard PIXI content (e.g. Mesh, Sprite, Graphics objects). - * * @memberof PIXI */ export class BatchGeometry extends Geometry { /** * Buffer used for position, color, texture IDs - * * @protected */ _buffer: Buffer; /** * Index buffer data - * * @protected */ _indexBuffer: Buffer; diff --git a/packages/core/src/batch/BatchPluginFactory.ts b/packages/core/src/batch/BatchPluginFactory.ts deleted file mode 100644 index 2a2f645e6f6..00000000000 --- a/packages/core/src/batch/BatchPluginFactory.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { BatchShaderGenerator } from './BatchShaderGenerator'; -import { BatchGeometry } from './BatchGeometry'; -import { AbstractBatchRenderer } from './AbstractBatchRenderer'; - -import defaultVertex from './texture.vert'; -import defaultFragment from './texture.frag'; - -import type { Renderer } from '../Renderer'; - -export interface IBatchFactoryOptions -{ - vertex?: string; - fragment?: string; - geometryClass?: typeof BatchGeometry; - vertexSize?: number; -} - -/** @memberof PIXI */ -export class BatchPluginFactory -{ - /** - * Create a new BatchRenderer plugin for Renderer. this convenience can provide an easy way - * to extend BatchRenderer with all the necessary pieces. - * @example - * const fragment = ` - * varying vec2 vTextureCoord; - * varying vec4 vColor; - * varying float vTextureId; - * uniform sampler2D uSamplers[%count%]; - * - * void main(void){ - * vec4 color; - * %forloop% - * gl_FragColor = vColor * vec4(color.a - color.rgb, color.a); - * } - * `; - * const InvertBatchRenderer = PIXI.BatchPluginFactory.create({ fragment }); - * PIXI.Renderer.registerPlugin('invert', InvertBatchRenderer); - * const sprite = new PIXI.Sprite(); - * sprite.pluginName = 'invert'; - * - * @param {object} [options] - * @param {string} [options.vertex=PIXI.BatchPluginFactory.defaultVertexSrc] - Vertex shader source - * @param {string} [options.fragment=PIXI.BatchPluginFactory.defaultFragmentTemplate] - Fragment shader template - * @param {number} [options.vertexSize=6] - Vertex size - * @param {object} [options.geometryClass=PIXI.BatchGeometry] - * @return {*} New batch renderer plugin - */ - static create(options?: IBatchFactoryOptions): typeof AbstractBatchRenderer - { - const { vertex, fragment, vertexSize, geometryClass } = Object.assign({ - vertex: defaultVertex, - fragment: defaultFragment, - geometryClass: BatchGeometry, - vertexSize: 6, - }, options); - - return class BatchPlugin extends AbstractBatchRenderer - { - constructor(renderer: Renderer) - { - super(renderer); - - this.shaderGenerator = new BatchShaderGenerator(vertex, fragment); - this.geometryClass = geometryClass; - this.vertexSize = vertexSize; - } - }; - } - - /** - * The default vertex shader source - * - * @readonly - */ - static get defaultVertexSrc(): string - { - return defaultVertex; - } - - /** - * The default fragment shader source - * - * @readonly - */ - static get defaultFragmentTemplate(): string - { - return defaultFragment; - } -} - -// Setup the default BatchRenderer plugin, this is what -// we'll actually export at the root level -export const BatchRenderer = BatchPluginFactory.create(); diff --git a/packages/core/src/batch/AbstractBatchRenderer.ts b/packages/core/src/batch/BatchRenderer.ts similarity index 89% rename from packages/core/src/batch/AbstractBatchRenderer.ts rename to packages/core/src/batch/BatchRenderer.ts index 4038158baea..ae8723cca4e 100644 --- a/packages/core/src/batch/AbstractBatchRenderer.ts +++ b/packages/core/src/batch/BatchRenderer.ts @@ -4,26 +4,30 @@ import { BaseTexture } from '../textures/BaseTexture'; import { ObjectRenderer } from './ObjectRenderer'; import { State } from '../state/State'; import { ViewableBuffer } from '../geometry/ViewableBuffer'; - +import { BatchShaderGenerator } from './BatchShaderGenerator'; import { checkMaxIfStatementsInShader } from '../shader/utils/checkMaxIfStatementsInShader'; import { settings } from '@pixi/settings'; import { premultiplyBlendMode, premultiplyTint, nextPow2, log2 } from '@pixi/utils'; import { ENV } from '@pixi/constants'; +import { BatchGeometry } from './BatchGeometry'; + +import defaultVertex from './texture.vert'; +import defaultFragment from './texture.frag'; import type { Renderer } from '../Renderer'; import type { Shader } from '../shader/Shader'; -import type { BatchShaderGenerator } from './BatchShaderGenerator'; -import type { BatchGeometry } from './BatchGeometry'; import type { Texture } from '../textures/Texture'; import type { BLEND_MODES } from '@pixi/constants'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * Interface for elements like Sprite, Mesh etc. for batching. - * * @memberof PIXI */ -export interface IBatchableElement { +export interface IBatchableElement +{ _texture: Texture; vertexData: Float32Array; indices: Uint16Array | Uint32Array | Array; @@ -40,18 +44,22 @@ export interface IBatchableElement { * with texture-based geometries and renders them in * batches. It uploads multiple textures to the GPU to * reduce to the number of draw calls. - * * @memberof PIXI */ -export class AbstractBatchRenderer extends ObjectRenderer +export class BatchRenderer extends ObjectRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'batch', + type: ExtensionType.RendererPlugin, + }; + /** The WebGL state in which this renderer will work. */ public readonly state: State; /** * The number of bufferable objects before a flush * occurs automatically. - * * @default settings.SPRITE_BATCH_SIZE * 4 */ public size: number; @@ -60,8 +68,7 @@ export class AbstractBatchRenderer extends ObjectRenderer * Maximum number of textures that can be uploaded to * the GPU under the current context. It is initialized * properly in `this.contextChange`. - * - * @see PIXI.AbstractBatchRenderer#contextChange + * @see PIXI.BatchRenderer#contextChange * @readonly */ public MAX_TEXTURES: number; @@ -82,7 +89,6 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * The class that represents the geometry of objects * that are going to be batched with this. - * * @member {object} * @default PIXI.BatchGeometry */ @@ -98,8 +104,7 @@ export class AbstractBatchRenderer extends ObjectRenderer * | aTextureCoords | 2 | * | aColor | 1 | * | aTextureId | 1 | - * - * @readonly + * @default 6 */ protected vertexSize: number; @@ -111,14 +116,12 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * Buffer of objects that are yet to be rendered. - * * @member {PIXI.DisplayObject[]} */ protected _bufferedElements: Array; /** * Data for texture batch builder, helps to save a bit of CPU on a pass. - * * @member {PIXI.BaseTexture[]} */ protected _bufferedTextures: Array; @@ -154,9 +157,8 @@ export class AbstractBatchRenderer extends ObjectRenderer * * The first buffer has a size of 8; each subsequent * buffer has double capacity of its previous. - * * @member {PIXI.ViewableBuffer[]} - * @see PIXI.AbstractBatchRenderer#getAttributeBuffer + * @see PIXI.BatchRenderer#getAttributeBuffer */ protected _aBuffers: Array; @@ -168,9 +170,8 @@ export class AbstractBatchRenderer extends ObjectRenderer * * The first buffer has a size of 12; each subsequent * buffer has double capacity of its previous. - * * @member {Uint16Array[]} - * @see PIXI.AbstractBatchRenderer#getIndexBuffer + * @see PIXI.BatchRenderer#getIndexBuffer */ protected _iBuffers: Array; protected _dcIndex: number; @@ -188,9 +189,8 @@ export class AbstractBatchRenderer extends ObjectRenderer * These are never re-allocated again, unless a * context change occurs; however, the pool may * be expanded if required. - * * @member {PIXI.Geometry[]} - * @see PIXI.AbstractBatchRenderer.contextChange + * @see PIXI.BatchRenderer.contextChange */ private _packedGeometries: Array; @@ -204,16 +204,15 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * This will hook onto the renderer's `contextChange` * and `prerender` signals. - * * @param {PIXI.Renderer} renderer - The renderer this works for. */ constructor(renderer: Renderer) { super(renderer); - this.shaderGenerator = null; - this.geometryClass = null; - this.vertexSize = null; + this.setShaderGenerator(); + this.geometryClass = BatchGeometry; + this.vertexSize = 6; this.state = State.for2d(); this.size = settings.SPRITE_BATCH_SIZE * 4; this._vertexCount = 0; @@ -241,6 +240,38 @@ export class AbstractBatchRenderer extends ObjectRenderer this._tempBoundTextures = []; } + /** + * The default vertex shader source + * @readonly + */ + static get defaultVertexSrc(): string + { + return defaultVertex; + } + + /** + * The default fragment shader source + * @readonly + */ + static get defaultFragmentTemplate(): string + { + return defaultFragment; + } + + /** + * Set the shader generator. + * @param {object} [options] + * @param {string} [options.vertex=PIXI.BatchRenderer.defaultVertexSrc] - Vertex shader source + * @param {string} [options.fragment=PIXI.BatchRenderer.defaultFragmentTemplate] - Fragment shader template + */ + public setShaderGenerator({ + vertex = BatchRenderer.defaultVertexSrc, + fragment = BatchRenderer.defaultFragmentTemplate + }: { vertex?: string, fragment?: string } = {}): void + { + this.shaderGenerator = new BatchShaderGenerator(vertex, fragment); + } + /** * Handles the `contextChange` signal. * @@ -285,7 +316,7 @@ export class AbstractBatchRenderer extends ObjectRenderer const { _drawCallPool, _textureArrayPool, - } = AbstractBatchRenderer; + } = BatchRenderer; // max draw calls const MAX_SPRITES = this.size / 4; // max texture arrays @@ -305,11 +336,7 @@ export class AbstractBatchRenderer extends ObjectRenderer } } - /** - * Handles the `prerender` signal. - * - * It ensures that flushes start from the first geometry object again. - */ + /** Handles the `prerender` signal. It ensures that flushes start from the first geometry object again. */ onPrerender(): void { this._flushId = 0; @@ -317,7 +344,6 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * Buffers the "batchable" object. It need not be rendered immediately. - * * @param {PIXI.DisplayObject} element - the element to render when * using this renderer */ @@ -345,7 +371,7 @@ export class AbstractBatchRenderer extends ObjectRenderer _bufferedTextures: textures, MAX_TEXTURES, } = this; - const textureArrays = AbstractBatchRenderer._textureArrayPool; + const textureArrays = BatchRenderer._textureArrayPool; const batch = this.renderer.batch; const boundTextures = this._tempBoundTextures; const touch = this.renderer.textureGC.count; @@ -398,7 +424,12 @@ export class AbstractBatchRenderer extends ObjectRenderer BaseTexture._globalBatch = TICK; } - /** Populating drawcalls for rendering */ + /** + * Populating drawcalls for rendering + * @param texArray + * @param start + * @param finish + */ buildDrawCalls(texArray: BatchTextureArray, start: number, finish: number): void { const { @@ -407,7 +438,7 @@ export class AbstractBatchRenderer extends ObjectRenderer _indexBuffer, vertexSize, } = this; - const drawCalls = AbstractBatchRenderer._drawCallPool; + const drawCalls = BatchRenderer._drawCallPool; let dcIndex = this._dcIndex; let aIndex = this._aIndex; @@ -454,7 +485,10 @@ export class AbstractBatchRenderer extends ObjectRenderer this._iIndex = iIndex; } - /** Bind textures for current rendering */ + /** + * Bind textures for current rendering + * @param texArray + */ bindAndClearTexArray(texArray: BatchTextureArray): void { const textureSystem = this.renderer.texture; @@ -505,7 +539,7 @@ export class AbstractBatchRenderer extends ObjectRenderer { const dcCount = this._dcIndex; const { gl, state: stateSystem } = this.renderer; - const drawCalls = AbstractBatchRenderer._drawCallPool; + const drawCalls = BatchRenderer._drawCallPool; let curTexArray = null; @@ -572,7 +606,7 @@ export class AbstractBatchRenderer extends ObjectRenderer this.flush(); } - /** Destroys this `AbstractBatchRenderer`. It cannot be used again. */ + /** Destroys this `BatchRenderer`. It cannot be used again. */ destroy(): void { for (let i = 0; i < this._packedGeometryPoolSize; i++) @@ -602,9 +636,8 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * Fetches an attribute buffer from `this._aBuffers` that can hold atleast `size` floats. - * * @param size - minimum capacity required - * @return - buffer than can hold atleast `size` floats + * @returns - buffer than can hold atleast `size` floats */ getAttributeBuffer(size: number): ViewableBuffer { @@ -631,9 +664,8 @@ export class AbstractBatchRenderer extends ObjectRenderer /** * Fetches an index buffer from `this._iBuffers` that can * have at least `size` capacity. - * * @param size - minimum required capacity - * @return - buffer that can fit `size` indices. + * @returns - buffer that can fit `size` indices. */ getIndexBuffer(size: number): Uint16Array { @@ -664,7 +696,6 @@ export class AbstractBatchRenderer extends ObjectRenderer * It uses these properties: `vertexData` `uvs`, `textureId` and * `indicies`. It also uses the "tint" of the base-texture, if * present. - * * @param {PIXI.DisplayObject} element - element being rendered * @param attributeBuffer - attribute buffer. * @param indexBuffer - index buffer @@ -714,7 +745,6 @@ export class AbstractBatchRenderer extends ObjectRenderer * * These are never re-allocated again. * Shared between all batch renderers because it can be only one "flush" working at the moment. - * * @member {PIXI.BatchDrawCall[]} */ static _drawCallPool: Array = []; @@ -725,8 +755,10 @@ export class AbstractBatchRenderer extends ObjectRenderer * * These are never re-allocated again. * Shared between all batch renderers because it can be only one "flush" working at the moment. - * * @member {PIXI.BatchTextureArray[]} */ static _textureArrayPool: Array = []; } + +// Install BatchRenderer as default +extensions.add(BatchRenderer); diff --git a/packages/core/src/batch/BatchShaderGenerator.ts b/packages/core/src/batch/BatchShaderGenerator.ts index 3dcaeced171..49a27cab457 100644 --- a/packages/core/src/batch/BatchShaderGenerator.ts +++ b/packages/core/src/batch/BatchShaderGenerator.ts @@ -5,7 +5,6 @@ import { Matrix } from '@pixi/math'; /** * Helper that generates batching multi-texture shader. Use it with your new BatchRenderer - * * @memberof PIXI */ export class BatchShaderGenerator @@ -31,12 +30,12 @@ export class BatchShaderGenerator this.programCache = {}; this.defaultGroupCache = {}; - if (fragTemplate.indexOf('%count%') < 0) + if (!fragTemplate.includes('%count%')) { throw new Error('Fragment template must contain "%count%".'); } - if (fragTemplate.indexOf('%forloop%') < 0) + if (!fragTemplate.includes('%forloop%')) { throw new Error('Fragment template must contain "%forloop%".'); } diff --git a/packages/core/src/batch/BatchSystem.ts b/packages/core/src/batch/BatchSystem.ts index cd76d0e064b..3e1525d1a8f 100644 --- a/packages/core/src/batch/BatchSystem.ts +++ b/packages/core/src/batch/BatchSystem.ts @@ -1,17 +1,24 @@ import { ObjectRenderer } from './ObjectRenderer'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; import type { BaseTexture } from '../textures/BaseTexture'; import type { BatchTextureArray } from './BatchTextureArray'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * System plugin to the renderer to manage batching. - * * @memberof PIXI */ export class BatchSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'batch', + }; + /** An empty renderer. */ public readonly emptyRenderer: ObjectRenderer; @@ -31,7 +38,6 @@ export class BatchSystem implements ISystem /** * Changes the current renderer to the one given in parameter - * * @param objectRenderer - The object renderer to use. */ setObjectRenderer(objectRenderer: ObjectRenderer): void @@ -56,9 +62,7 @@ export class BatchSystem implements ISystem this.setObjectRenderer(this.emptyRenderer); } - /** - * Reset the system to an empty renderer - */ + /** Reset the system to an empty renderer */ reset(): void { this.setObjectRenderer(this.emptyRenderer); @@ -67,7 +71,6 @@ export class BatchSystem implements ISystem /** * Handy function for batch renderers: copies bound textures in first maxTextures locations to array * sets actual _batchLocation for them - * * @param arr - arr copy destination * @param maxTextures - number of copied elements */ @@ -89,7 +92,6 @@ export class BatchSystem implements ISystem * Assigns batch locations to textures in array based on boundTextures state. * All textures in texArray should have `_batchEnabled = _batchId`, * and their count should be less than `maxTextures`. - * * @param texArray - textures to bound * @param boundTextures - current state of bound textures * @param batchId - marker for _batchEnabled param of textures in texArray @@ -140,3 +142,5 @@ export class BatchSystem implements ISystem this.renderer = null; } } + +extensions.add(BatchSystem); diff --git a/packages/core/src/batch/BatchTextureArray.ts b/packages/core/src/batch/BatchTextureArray.ts index adaf65a2370..29d51dd40c9 100644 --- a/packages/core/src/batch/BatchTextureArray.ts +++ b/packages/core/src/batch/BatchTextureArray.ts @@ -3,7 +3,6 @@ import type { BaseTexture } from '@pixi/core'; /** * Used by the batcher to build texture batches. * Holds list of textures and their respective locations. - * * @memberof PIXI */ export class BatchTextureArray diff --git a/packages/core/src/batch/ObjectRenderer.ts b/packages/core/src/batch/ObjectRenderer.ts index 02d9c786579..979d7706460 100644 --- a/packages/core/src/batch/ObjectRenderer.ts +++ b/packages/core/src/batch/ObjectRenderer.ts @@ -1,10 +1,9 @@ -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; /** * Base for a common object renderer that can be used as a * system renderer plugin. - * * @memberof PIXI */ export class ObjectRenderer implements ISystem @@ -20,19 +19,13 @@ export class ObjectRenderer implements ISystem this.renderer = renderer; } - /** - * Stub method that should be used to empty the current - * batch by rendering objects now. - */ + /** Stub method that should be used to empty the current batch by rendering objects now. */ flush(): void { // flush! } - /** - * Generic destruction method that frees all resources. This - * should be called by subclasses. - */ + /** Generic destruction method that frees all resources. This should be called by subclasses. */ destroy(): void { this.renderer = null; @@ -49,10 +42,7 @@ export class ObjectRenderer implements ISystem // set the shader.. } - /** - * Stops the renderer. It should free up any state and - * become dormant. - */ + /** Stops the renderer. It should free up any state and become dormant. */ stop(): void { this.flush(); @@ -61,8 +51,7 @@ export class ObjectRenderer implements ISystem /** * Keeps the object to render. It doesn't have to be * rendered immediately. - * - * @param {PIXI.DisplayObject} object - The object to render. + * @param {PIXI.DisplayObject} _object - The object to render. */ render(_object: any): void // eslint-disable-line @typescript-eslint/explicit-module-boundary-types { diff --git a/packages/core/src/context/ContextSystem.ts b/packages/core/src/context/ContextSystem.ts index 365371a5b44..bf4f0998d26 100644 --- a/packages/core/src/context/ContextSystem.ts +++ b/packages/core/src/context/ContextSystem.ts @@ -1,46 +1,76 @@ import { ENV } from '@pixi/constants'; import { settings } from '../settings'; -import type { ISystem } from '../ISystem'; -import type { IRenderingContext } from '../IRenderingContext'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; import type { WebGLExtensions } from './WebGLExtensions'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; let CONTEXT_UID_COUNTER = 0; -export interface ISupportDict { +export interface ISupportDict +{ uint32Indices: boolean; } +export interface ContextOptions +{ + context?: IRenderingContext; + /** + * Use premultipliedAlpha instead + * @deprecated since 7.0.0 + */ + useContextAlpha?: boolean | 'notMultiplied'; + premultipliedAlpha?: boolean; + powerPreference?: WebGLPowerPreference; + preserveDrawingBuffer?: boolean; + antialias?: boolean; +} + /** * System plugin to the renderer to manage the context. - * * @memberof PIXI */ export class ContextSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'context', + }; + /** * Either 1 or 2 to reflect the WebGL version being used. - * * @readonly */ public webGLVersion: number; /** * Features supported by current context. - * * @type {object} * @readonly * @property {boolean} uint32Indices - Support for 32-bit indices buffer. */ readonly supports: ISupportDict; + preserveDrawingBuffer: boolean; + powerPreference: WebGLPowerPreference; + + /** + * Pass-thru setting for the canvas' context `alpha` property. This is typically + * not something you need to fiddle with. If you want transparency, use `backgroundAlpha`. + * @member {boolean} + * @deprecated since 7.0.0 + */ + useContextAlpha: boolean | 'notMultiplied'; + protected CONTEXT_UID: number; protected gl: IRenderingContext; /** * Extensions available. - * * @type {object} * @readonly * @property {WEBGL_draw_buffers} drawBuffers - WebGL v1 extension @@ -69,14 +99,10 @@ export class ContextSystem implements ISystem // Bind functions this.handleContextLost = this.handleContextLost.bind(this); this.handleContextRestored = this.handleContextRestored.bind(this); - - (renderer.view as any).addEventListener('webglcontextlost', this.handleContextLost, false); - renderer.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); } /** * `true` if the context is lost - * * @readonly */ get isLost(): boolean @@ -86,7 +112,6 @@ export class ContextSystem implements ISystem /** * Handles the context change event. - * * @param {WebGLRenderingContext} gl - New WebGL context. */ protected contextChange(gl: IRenderingContext): void @@ -102,9 +127,37 @@ export class ContextSystem implements ISystem } } + init(options: ContextOptions): void + { + /* + * The options passed in to create a new WebGL context. + */ + if (options.context) + { + this.initFromContext(options.context); + } + else + { + const alpha = this.renderer.background.alpha < 1; + const premultipliedAlpha = options.premultipliedAlpha ?? true; + + this.preserveDrawingBuffer = options.preserveDrawingBuffer; + this.useContextAlpha = options.useContextAlpha; + this.powerPreference = options.powerPreference; + + this.initFromOptions({ + alpha, + premultipliedAlpha, + antialias: options.antialias, + stencil: true, + preserveDrawingBuffer: options.preserveDrawingBuffer, + powerPreference: options.powerPreference, + }); + } + } + /** * Initializes the context. - * * @protected * @param {WebGLRenderingContext} gl - WebGL context */ @@ -115,11 +168,13 @@ export class ContextSystem implements ISystem this.renderer.gl = gl; this.renderer.CONTEXT_UID = CONTEXT_UID_COUNTER++; this.renderer.runners.contextChange.emit(gl); + + (this.renderer.view as any).addEventListener('webglcontextlost', this.handleContextLost, false); + this.renderer.view.addEventListener('webglcontextrestored', this.handleContextRestored, false); } /** * Initialize from context options - * * @protected * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext * @param {object} options - context attributes @@ -133,12 +188,11 @@ export class ContextSystem implements ISystem /** * Helper class to create a WebGL Context - * * @param canvas - the canvas element that we will get the context from * @param options - An options object that gets passed in to the canvas element containing the * context attributes * @see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext - * @return {WebGLRenderingContext} the WebGL context + * @returns {WebGLRenderingContext} the WebGL context */ createContext(canvas: HTMLCanvasElement, options: WebGLContextAttributes): IRenderingContext { @@ -157,8 +211,7 @@ export class ContextSystem implements ISystem { this.webGLVersion = 1; - gl = canvas.getContext('webgl', options) - || canvas.getContext('experimental-webgl', options); + gl = canvas.getContext('webgl', options) || canvas.getContext('experimental-webgl', options); if (!gl) { @@ -222,7 +275,6 @@ export class ContextSystem implements ISystem /** * Handles a lost webgl context - * * @param {WebGLContextEvent} event - The context lost event. */ protected handleContextLost(event: WebGLContextEvent): void @@ -257,7 +309,7 @@ export class ContextSystem implements ISystem /** Handle the post-render runner event. */ protected postrender(): void { - if (this.renderer.renderingToScreen) + if (this.renderer.objectRenderer.renderingToScreen) { this.gl.flush(); } @@ -265,7 +317,6 @@ export class ContextSystem implements ISystem /** * Validate context. - * * @param {WebGLRenderingContext} gl - Render context. */ protected validateContext(gl: IRenderingContext): void @@ -280,7 +331,7 @@ export class ContextSystem implements ISystem } // this is going to be fairly simple for now.. but at least we have room to grow! - if (!attributes.stencil) + if (attributes && !attributes.stencil) { /* eslint-disable max-len, no-console */ console.warn('Provided WebGL context does not have a stencil buffer, masks may not render correctly'); @@ -299,3 +350,5 @@ export class ContextSystem implements ISystem } } } + +extensions.add(ContextSystem); diff --git a/packages/core/src/context/WebGLExtensions.ts b/packages/core/src/context/WebGLExtensions.ts index eeb8b82eb83..aae4036faa4 100644 --- a/packages/core/src/context/WebGLExtensions.ts +++ b/packages/core/src/context/WebGLExtensions.ts @@ -30,7 +30,8 @@ export interface WEBGL_compressed_texture_atc COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: number; } -export interface WebGLExtensions { +export interface WebGLExtensions +{ drawBuffers?: WEBGL_draw_buffers; depthTexture?: OES_texture_float; loseContext?: WEBGL_lose_context; diff --git a/packages/core/src/deprecations.ts b/packages/core/src/deprecations.ts index aa53df402cf..e69de29bb2d 100644 --- a/packages/core/src/deprecations.ts +++ b/packages/core/src/deprecations.ts @@ -1,51 +0,0 @@ -import { deprecation } from '@pixi/utils'; -import * as _systems from './systems'; -import * as _resources from './textures/resources'; - -/** - * @memberof PIXI - * @namespace resources - * @see PIXI - * @deprecated since 6.0.0 - */ -const resources = {}; - -for (const name in _resources) -{ - Object.defineProperty(resources, name, - { - get() - { - // #if _DEBUG - deprecation('6.0.0', `PIXI.systems.${name} has moved to PIXI.${name}`); - // #endif - - return (_resources as any)[name]; - }, - }); -} - -/** - * @memberof PIXI - * @namespace systems - * @see PIXI - * @deprecated since 6.0.0 - */ -const systems = {}; - -for (const name in _systems) -{ - Object.defineProperty(systems, name, - { - get() - { - // #if _DEBUG - deprecation('6.0.0', `PIXI.resources.${name} has moved to PIXI.${name}`); - // #endif - - return (_systems as any)[name]; - }, - }); -} - -export { resources, systems }; diff --git a/packages/core/src/filters/Filter.ts b/packages/core/src/filters/Filter.ts index a4fd6045f44..5bd67775c5c 100644 --- a/packages/core/src/filters/Filter.ts +++ b/packages/core/src/filters/Filter.ts @@ -1,16 +1,15 @@ -import { Shader } from '../shader/Shader'; +import { settings } from '@pixi/settings'; import { Program } from '../shader/Program'; +import { Shader } from '../shader/Shader'; import { State } from '../state/State'; -import { settings } from '@pixi/settings'; -import { MSAA_QUALITY } from '@pixi/constants'; -import defaultVertex from './defaultFilter.vert'; import defaultFragment from './defaultFilter.frag'; +import defaultVertex from './defaultFilter.vert'; +import type { MSAA_QUALITY, BLEND_MODES, CLEAR_MODES } from '@pixi/constants'; +import type { Dict } from '@pixi/utils'; import type { RenderTexture } from '../renderTexture/RenderTexture'; -import type { FilterSystem } from './FilterSystem'; import type { FilterState } from './FilterState'; -import type { BLEND_MODES, CLEAR_MODES } from '@pixi/constants'; -import type { Dict } from '@pixi/utils'; +import type { FilterSystem } from './FilterSystem'; /** * A filter is a special shader that applies post-processing effects to an input texture and writes into an output @@ -179,7 +178,6 @@ import type { Dict } from '@pixi/utils'; * * Since PixiJS only had a handful of built-in filters, additional filters can be downloaded * {@link https://github.com/pixijs/pixi-filters here} from the PixiJS Filters repository. - * * @memberof PIXI */ export class Filter extends Shader @@ -200,14 +198,12 @@ export class Filter extends Shader /** * If enabled, PixiJS will fit the filter area into boundaries for better performance. * Switch it off if it does not work for specific shader. - * * @default true */ public autoFit: boolean; /** * Legacy filters use position and uvs from attributes (set by filter system) - * * @readonly */ public legacy: boolean; @@ -239,12 +235,11 @@ export class Filter extends Shader /** * Applies the filter - * * @param {PIXI.FilterSystem} filterManager - The renderer to retrieve the filter from * @param {PIXI.RenderTexture} input - The input render target. * @param {PIXI.RenderTexture} output - The target to output to. * @param {PIXI.CLEAR_MODES} [clearMode] - Should the output be cleared before rendering to it. - * @param {object} [currentState] - It's current state of filter. + * @param {object} [_currentState] - It's current state of filter. * There are some useful properties in the currentState : * target, filters, sourceFrame, destinationFrame, renderTarget, resolution */ @@ -260,7 +255,6 @@ export class Filter extends Shader /** * Sets the blend mode of the filter. - * * @default PIXI.BLEND_MODES.NORMAL */ get blendMode(): BLEND_MODES @@ -289,7 +283,6 @@ export class Filter extends Shader /** * The default vertex shader source - * * @constant */ static get defaultVertexSrc(): string @@ -299,7 +292,6 @@ export class Filter extends Shader /** * The default fragment shader source - * * @constant */ static get defaultFragmentSrc(): string diff --git a/packages/core/src/filters/FilterState.ts b/packages/core/src/filters/FilterState.ts index ef601e0e844..693145ff228 100644 --- a/packages/core/src/filters/FilterState.ts +++ b/packages/core/src/filters/FilterState.ts @@ -1,4 +1,5 @@ -import { Matrix, Rectangle } from '@pixi/math'; +import type { Matrix } from '@pixi/math'; +import { Rectangle } from '@pixi/math'; import { MSAA_QUALITY } from '@pixi/constants'; import type { Filter } from './Filter'; @@ -7,7 +8,6 @@ import type { RenderTexture } from '../renderTexture/RenderTexture'; /** * System plugin to the renderer to manage filter states. - * * @ignore */ export class FilterState diff --git a/packages/core/src/filters/FilterSystem.ts b/packages/core/src/filters/FilterSystem.ts index b46564b5a83..c4422a240e6 100644 --- a/packages/core/src/filters/FilterSystem.ts +++ b/packages/core/src/filters/FilterSystem.ts @@ -6,12 +6,14 @@ import { UniformGroup } from '../shader/UniformGroup'; import { DRAW_MODES, CLEAR_MODES, MSAA_QUALITY } from '@pixi/constants'; import { FilterState } from './FilterState'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Filter } from './Filter'; import type { IFilterTarget } from './IFilterTarget'; import type { ISpriteMaskTarget } from './spriteMask/SpriteMaskFilter'; import type { RenderTexture } from '../renderTexture/RenderTexture'; import type { Renderer } from '../Renderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; const tempPoints = [new Point(), new Point(), new Point(), new Point()]; const tempMatrix = new Matrix(); @@ -33,20 +35,25 @@ const tempMatrix = new Matrix(); * * {@link PIXI.Container#renderAdvanced} is an example of how to use the filter system. It is a 3 step process: * - * * **push**: Use {@link PIXI.FilterSystem#push} to push the set of filters to be applied on a filter-target. - * * **render**: Render the contents to be filtered using the renderer. The filter-system will only capture the contents + * **push**: Use {@link PIXI.FilterSystem#push} to push the set of filters to be applied on a filter-target. + * **render**: Render the contents to be filtered using the renderer. The filter-system will only capture the contents * inside the bounds of the filter-target. NOTE: Using {@link PIXI.Renderer#render} is * illegal during an existing render cycle, and it may reset the filter system. - * * **pop**: Use {@link PIXI.FilterSystem#pop} to pop & execute the filters you initially pushed. It will apply them + * **pop**: Use {@link PIXI.FilterSystem#pop} to pop & execute the filters you initially pushed. It will apply them * serially and output to the bounds of the filter-target. - * * @memberof PIXI */ export class FilterSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'filter', + }; + /** * List of filters for the FilterSystem - * @member {Object[]} + * @member {object[]} */ public readonly defaultFilterStack: Array; @@ -80,14 +87,13 @@ export class FilterSystem implements ISystem /** * This uniform group is attached to filter uniforms when used. - * - * @property {PIXI.Rectangle} outputFrame - * @property {Float32Array} inputSize - * @property {Float32Array} inputPixel - * @property {Float32Array} inputClamp - * @property {Number} resolution - * @property {Float32Array} filterArea - * @property {Float32Array} filterClamp + * @property {PIXI.Rectangle} outputFrame - + * @property {Float32Array} inputSize - + * @property {Float32Array} inputPixel - + * @property {Float32Array} inputClamp - + * @property {number} resolution - + * @property {Float32Array} filterArea - + * @property {Float32Array} filterClamp - */ protected globalUniforms: UniformGroup; @@ -105,7 +111,7 @@ export class FilterSystem implements ISystem this.defaultFilterStack = [{}] as any; this.texturePool = new RenderTexturePool(); - this.texturePool.setScreenSize(renderer.view); + this.statePool = []; this.quad = new Quad(); @@ -129,10 +135,14 @@ export class FilterSystem implements ISystem this.useMaxPadding = false; } + init(): void + { + this.texturePool.setScreenSize(this.renderer.view); + } + /** * Pushes a set of filters to be applied later to the system. This will redirect further rendering into an * input render-texture for the rest of the filtering pipeline. - * * @param {PIXI.DisplayObject} target - The target of the filter to render. * @param filters - The filters to apply. */ @@ -188,20 +198,31 @@ export class FilterSystem implements ISystem state.sourceFrame.pad(padding); + const sourceFrameProjected = this.tempRect.copyFrom(renderTextureSystem.sourceFrame); + + // Project source frame into world space (if projection is applied) + if (renderer.projection.transform) + { + this.transformAABB( + tempMatrix.copyFrom(renderer.projection.transform).invert(), + sourceFrameProjected + ); + } + if (autoFit) { - const sourceFrameProjected = this.tempRect.copyFrom(renderTextureSystem.sourceFrame); + state.sourceFrame.fit(sourceFrameProjected); - // Project source frame into world space (if projection is applied) - if (renderer.projection.transform) + if (state.sourceFrame.width <= 0 || state.sourceFrame.height <= 0) { - this.transformAABB( - tempMatrix.copyFrom(renderer.projection.transform).invert(), - sourceFrameProjected - ); + state.sourceFrame.width = 0; + state.sourceFrame.height = 0; } - - state.sourceFrame.fit(sourceFrameProjected); + } + else if (!state.sourceFrame.intersects(sourceFrameProjected)) + { + state.sourceFrame.width = 0; + state.sourceFrame.height = 0; } // Round sourceFrame in screen space based on render-texture. @@ -348,7 +369,6 @@ export class FilterSystem implements ISystem /** * Binds a renderTexture with corresponding `filterFrame`, clears it if mode corresponds. - * * @param filterTexture - renderTexture to bind, should belong to filter pool or filter stack * @param clearMode - clearMode, by default its CLEAR/YES. See {@link PIXI.CLEAR_MODES} */ @@ -370,7 +390,7 @@ export class FilterSystem implements ISystem this.renderer.projection.transform = null; } - if (filterTexture && filterTexture.filterFrame) + if (filterTexture?.filterFrame) { const destinationFrame = this.tempRect; @@ -413,7 +433,6 @@ export class FilterSystem implements ISystem * Draws a filter using the default rendering process. * * This should be called only by {@link Filter#apply}. - * * @param filter - The filter to draw. * @param input - The input render target. * @param output - The target to output to. @@ -457,10 +476,9 @@ export class FilterSystem implements ISystem * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_. * * Use `outputMatrix * vTextureCoord` in the shader. - * * @param outputMatrix - The matrix to output to. * @param {PIXI.Sprite} sprite - The sprite to map to. - * @return The mapped matrix. + * @returns The mapped matrix. */ calculateSpriteMatrix(outputMatrix: Matrix, sprite: ISpriteMaskTarget): Matrix { @@ -489,12 +507,11 @@ export class FilterSystem implements ISystem /** * Gets a Power-of-Two render texture or fullScreen texture - * * @param minWidth - The minimum width of the render texture in real pixels. * @param minHeight - The minimum height of the render texture in real pixels. * @param resolution - The resolution of the render texture. * @param multisample - Number of samples of the render texture. - * @return - The new render texture. + * @returns - The new render texture. */ protected getOptimalFilterTexture(minWidth: number, minHeight: number, resolution = 1, multisample: MSAA_QUALITY = MSAA_QUALITY.NONE): RenderTexture @@ -505,7 +522,6 @@ export class FilterSystem implements ISystem /** * Gets extra render texture to use inside current filter * To be compliant with older filters, you can use params in any order - * * @param input - renderTexture from which size and resolution will be copied * @param resolution - override resolution of the renderTexture * @param multisample - number of samples of the renderTexture @@ -532,7 +548,6 @@ export class FilterSystem implements ISystem /** * Frees a render texture back into the pool. - * * @param renderTexture - The renderTarget to free */ returnFilterTexture(renderTexture: RenderTexture): void @@ -630,3 +645,5 @@ export class FilterSystem implements ISystem this.transformAABB(transform.invert(), frame); } } + +extensions.add(FilterSystem); diff --git a/packages/core/src/filters/spriteMask/SpriteMaskFilter.ts b/packages/core/src/filters/spriteMask/SpriteMaskFilter.ts index f6496fb026c..042cc2bdfcd 100644 --- a/packages/core/src/filters/spriteMask/SpriteMaskFilter.ts +++ b/packages/core/src/filters/spriteMask/SpriteMaskFilter.ts @@ -1,6 +1,7 @@ import { Filter } from '../Filter'; -import { Matrix, Point } from '@pixi/math'; -import { CLEAR_MODES } from '@pixi/constants'; +import type { Point } from '@pixi/math'; +import { Matrix } from '@pixi/math'; +import type { CLEAR_MODES } from '@pixi/constants'; import vertex from './spriteMaskFilter.vert'; import fragment from './spriteMaskFilter.frag'; import { TextureMatrix } from '../../textures/TextureMatrix'; @@ -27,7 +28,6 @@ export interface ISpriteMaskFilter extends Filter * This handles a Sprite acting as a mask, as opposed to a Graphic. * * WebGL only. - * * @memberof PIXI */ export class SpriteMaskFilter extends Filter @@ -71,7 +71,6 @@ export class SpriteMaskFilter extends Filter /** * Sprite mask - * * @type {PIXI.DisplayObject} */ get maskSprite(): IMaskTarget @@ -91,7 +90,6 @@ export class SpriteMaskFilter extends Filter /** * Applies the filter - * * @param filterManager - The renderer to retrieve the filter from * @param input - The input render target. * @param output - The target to output to. diff --git a/packages/core/src/framebuffer/Framebuffer.ts b/packages/core/src/framebuffer/Framebuffer.ts index 7e5f7206c37..29c5f7f7615 100644 --- a/packages/core/src/framebuffer/Framebuffer.ts +++ b/packages/core/src/framebuffer/Framebuffer.ts @@ -10,7 +10,6 @@ import type { GLFramebuffer } from './GLFramebuffer'; * one internally to render into itself. You can attach a depth or stencil buffer to a framebuffer. * * On WebGL 2 machines, shaders can output to multiple textures simultaneously with GLSL 300 ES. - * * @memberof PIXI */ export class Framebuffer @@ -34,7 +33,6 @@ export class Framebuffer * renderer.render(myContainer, {renderTexture}); * renderer.framebuffer.blit(); // copies data from MSAA framebuffer to texture * ``` - * * @default PIXI.MSAA_QUALITY.NONE */ public multisample: MSAA_QUALITY; @@ -76,7 +74,6 @@ export class Framebuffer /** * Reference to the colorTexture. - * * @readonly */ get colorTexture(): BaseTexture @@ -86,7 +83,6 @@ export class Framebuffer /** * Add texture to the colorTexture array. - * * @param index - Index of the array to add the texture to * @param texture - Texture to add to the array */ @@ -109,7 +105,6 @@ export class Framebuffer /** * Add a depth texture to the frame buffer. - * * @param texture - Texture to add. */ addDepthTexture(texture?: BaseTexture): this @@ -155,7 +150,6 @@ export class Framebuffer /** * Resize the frame buffer - * * @param width - Width of the frame buffer to resize to * @param height - Height of the frame buffer to resize to */ diff --git a/packages/core/src/framebuffer/FramebufferSystem.ts b/packages/core/src/framebuffer/FramebufferSystem.ts index f550c2461f8..e8ab2a08904 100644 --- a/packages/core/src/framebuffer/FramebufferSystem.ts +++ b/packages/core/src/framebuffer/FramebufferSystem.ts @@ -4,19 +4,26 @@ import { settings } from '../settings'; import { Framebuffer } from './Framebuffer'; import { GLFramebuffer } from './GLFramebuffer'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; -import type { IRenderingContext } from '../IRenderingContext'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; const tempRectangle = new Rectangle(); /** * System plugin to the renderer to manage framebuffers. - * * @memberof PIXI */ export class FramebufferSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'framebuffer', + }; + /** A list of managed framebuffers. */ public readonly managedFramebuffers: Array; public current: Framebuffer; @@ -98,7 +105,6 @@ export class FramebufferSystem implements ISystem /** * Bind a framebuffer. - * * @param framebuffer * @param frame - frame, default is framebuffer size * @param mipLevel - optional mip level to set on the framebuffer - defaults to 0 @@ -200,7 +206,6 @@ export class FramebufferSystem implements ISystem /** * Set the WebGLRenderingContext's viewport. - * * @param x - X position of viewport * @param y - Y position of viewport * @param width - Width of viewport @@ -228,7 +233,6 @@ export class FramebufferSystem implements ISystem /** * Get the size of the current width and height. Returns object with `width` and `height` values. - * * @readonly */ get size(): { x: number; y: number; width: number; height: number } @@ -244,7 +248,6 @@ export class FramebufferSystem implements ISystem /** * Clear the color of the context - * * @param r - Red value from 0 to 1 * @param g - Green value from 0 to 1 * @param b - Blue value from 0 to 1 @@ -263,7 +266,6 @@ export class FramebufferSystem implements ISystem /** * Initialize framebuffer for this context - * * @protected * @param framebuffer * @returns - created GLFramebuffer @@ -284,7 +286,7 @@ export class FramebufferSystem implements ISystem /** * Resize the framebuffer - * + * @param framebuffer * @protected */ resizeFramebuffer(framebuffer: Framebuffer): void @@ -340,7 +342,8 @@ export class FramebufferSystem implements ISystem /** * Update the framebuffer - * + * @param framebuffer + * @param mipLevel * @protected */ updateFramebuffer(framebuffer: Framebuffer, mipLevel: number): void @@ -450,7 +453,10 @@ export class FramebufferSystem implements ISystem } } - /** Returns true if the frame buffer can be multisampled. */ + /** + * Returns true if the frame buffer can be multisampled. + * @param framebuffer + */ protected canMultisampleFramebuffer(framebuffer: Framebuffer): boolean { return this.renderer.context.webGLVersion !== 1 @@ -459,7 +465,6 @@ export class FramebufferSystem implements ISystem /** * Detects number of samples that is not more than a param but as close to it as possible - * * @param samples - number of samples * @returns - recommended number of samples */ @@ -496,7 +501,6 @@ export class FramebufferSystem implements ISystem * after that target framebuffer is bound * * Fails with WebGL warning if blits multisample framebuffer to different size - * * @param framebuffer - by default it blits "into itself", from renderBuffer to texture. * @param sourcePixels - source rectangle in pixels * @param destPixels - dest rectangle in pixels, assumed to be the same as sourcePixels @@ -582,7 +586,6 @@ export class FramebufferSystem implements ISystem /** * Disposes framebuffer. - * * @param framebuffer - framebuffer that has to be disposed of * @param contextLost - If context was lost, we suppress all delete function calls */ @@ -630,7 +633,6 @@ export class FramebufferSystem implements ISystem /** * Disposes all framebuffers, but not textures bound to them. - * * @param [contextLost=false] - If context was lost, we suppress all delete function calls */ disposeAll(contextLost?: boolean): void @@ -650,7 +652,6 @@ export class FramebufferSystem implements ISystem * Used by MaskSystem, when its time to use stencil mask for Graphics element. * * Its an alternative for public lazy `framebuffer.enableStencil`, in case we need stencil without rebind. - * * @private */ forceStencil(): void @@ -691,11 +692,7 @@ export class FramebufferSystem implements ISystem gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencil); } - /** - * Resets framebuffer stored state, binds screen framebuffer. - * - * Should be called before renderTexture reset(). - */ + /** Resets framebuffer stored state, binds screen framebuffer. Should be called before renderTexture reset(). */ reset(): void { this.current = this.unknownFramebuffer; @@ -707,3 +704,5 @@ export class FramebufferSystem implements ISystem this.renderer = null; } } + +extensions.add(FramebufferSystem); diff --git a/packages/core/src/framebuffer/GLFramebuffer.ts b/packages/core/src/framebuffer/GLFramebuffer.ts index 64d3dea0853..bd3e282cec7 100644 --- a/packages/core/src/framebuffer/GLFramebuffer.ts +++ b/packages/core/src/framebuffer/GLFramebuffer.ts @@ -4,7 +4,6 @@ import type { Framebuffer } from './Framebuffer'; /** * Internal framebuffer for WebGL context. - * * @memberof PIXI */ export class GLFramebuffer diff --git a/packages/core/src/framebuffer/MultisampleSystem.ts b/packages/core/src/framebuffer/MultisampleSystem.ts new file mode 100644 index 00000000000..cebbb60a5d0 --- /dev/null +++ b/packages/core/src/framebuffer/MultisampleSystem.ts @@ -0,0 +1,82 @@ +import { MSAA_QUALITY } from '@pixi/constants'; +import type { ISystem } from '../system/ISystem'; +import type { Renderer } from '../Renderer'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; + +/** + * System that manages the multisample property on the WebGL renderer + * @memberof PIXI + */ +export class MultisampleSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: '_multisample', + }; + + /** + * The number of msaa samples of the canvas. + * @readonly + */ + public multisample: MSAA_QUALITY; + + private renderer: Renderer; + + constructor(renderer: Renderer) + { + this.renderer = renderer; + } + + protected contextChange(gl: IRenderingContext): void + { + let samples; + + if (this.renderer.context.webGLVersion === 1) + { + const framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + samples = gl.getParameter(gl.SAMPLES); + + gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); + } + else + { + const framebuffer = gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING); + + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); + + samples = gl.getParameter(gl.SAMPLES); + + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, framebuffer); + } + + if (samples >= MSAA_QUALITY.HIGH) + { + this.multisample = MSAA_QUALITY.HIGH; + } + else if (samples >= MSAA_QUALITY.MEDIUM) + { + this.multisample = MSAA_QUALITY.MEDIUM; + } + else if (samples >= MSAA_QUALITY.LOW) + { + this.multisample = MSAA_QUALITY.LOW; + } + else + { + this.multisample = MSAA_QUALITY.NONE; + } + } + + destroy(): void + { + // ka boom! + } +} + +extensions.add(MultisampleSystem); diff --git a/packages/core/src/geometry/Attribute.ts b/packages/core/src/geometry/Attribute.ts index 25410941173..310245ccc95 100644 --- a/packages/core/src/geometry/Attribute.ts +++ b/packages/core/src/geometry/Attribute.ts @@ -7,7 +7,6 @@ import { TYPES } from '@pixi/constants'; * * This does not contain the actual data, but instead has a buffer id that maps to a {@link PIXI.Buffer} * This can include anything from positions, uvs, normals, colors etc. - * * @memberof PIXI */ export class Attribute @@ -48,7 +47,6 @@ export class Attribute /** * Helper function that creates an Attribute based on the information provided - * * @param buffer - the id of the buffer that this attribute will look for * @param [size=0] - the size of the attribute. If you have 2 floats per vertex (eg position x and y) this would be 2 * @param [normalized=false] - should the data be normalized. diff --git a/packages/core/src/geometry/Buffer.ts b/packages/core/src/geometry/Buffer.ts index 890ca477943..564560feb83 100644 --- a/packages/core/src/geometry/Buffer.ts +++ b/packages/core/src/geometry/Buffer.ts @@ -1,6 +1,5 @@ import { BUFFER_TYPE } from '@pixi/constants'; import { Runner } from '@pixi/runner'; - import type { GLBuffer } from './GLBuffer'; let UID = 0; @@ -21,8 +20,7 @@ export interface IArrayBuffer extends ArrayBuffer * to support expressions like `geometry.buffers[0].data[0] = position.x`. * * Gives access to indexing and `length` field - * - * @popelyshev: If data is actually ArrayBuffer and throws Exception on indexing - its user problem :) + * * @popelyshev: If data is actually ArrayBuffer and throws Exception on indexing - its user problem :) */ export interface ITypedArray extends IArrayBuffer { @@ -33,15 +31,13 @@ export interface ITypedArray extends IArrayBuffer /** * A wrapper for data so that it can be used and uploaded by WebGL - * * @memberof PIXI */ export class Buffer { /** * The data in the buffer, as a typed array - * - * @type {ArrayBuffer| SharedArrayBuffer | ArrayBufferView} + * @type {PIXI.IArrayBuffer} */ public data: ITypedArray; @@ -55,19 +51,18 @@ export class Buffer public static: boolean; public id: number; - disposeRunner: Runner; + disposeRunner: Runner; /** * A map of renderer IDs to webgl buffer - * * @private - * @type {object} + * @type {Object} */ _glBuffers: {[key: number]: GLBuffer}; _updateID: number; /** - * @param {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} data - the data to store in the buffer. + * @param {PIXI.IArrayBuffer} data - the data to store in the buffer. * @param _static - `true` for static buffer * @param index - `true` for index buffer */ @@ -88,7 +83,7 @@ export class Buffer // TODO could explore flagging only a partial upload? /** * Flags this buffer as requiring an upload to the GPU. - * @param {ArrayBuffer|SharedArrayBuffer|ArrayBufferView|number[]} [data] - the data to update in the buffer. + * @param {PIXI.IArrayBuffer|number[]} [data] - the data to update in the buffer. */ update(data?: IArrayBuffer | Array): void { @@ -134,9 +129,8 @@ export class Buffer /** * Helper function that creates a buffer based on an array or TypedArray - * * @param {ArrayBufferView | number[]} data - the TypedArray that the buffer will store. If this is a regular Array it will be converted to a Float32Array. - * @return - A new Buffer based on the data provided. + * @returns - A new Buffer based on the data provided. */ static from(data: IArrayBuffer | number[]): Buffer { diff --git a/packages/core/src/geometry/BufferSystem.ts b/packages/core/src/geometry/BufferSystem.ts index ab10ef1e0d9..f16710572cd 100644 --- a/packages/core/src/geometry/BufferSystem.ts +++ b/packages/core/src/geometry/BufferSystem.ts @@ -1,9 +1,11 @@ import { GLBuffer } from './GLBuffer'; import type { Renderer } from '../Renderer'; -import type { IRenderingContext } from '../IRenderingContext'; import type { Buffer } from './Buffer'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * System plugin to the renderer to manage buffers. @@ -19,13 +21,17 @@ import type { ISystem } from '../ISystem'; * This system will handle the binding of buffers to the GPU as well as uploading * them. With this system, you never need to work directly with GPU buffers, but instead work with * the PIXI.Buffer class. - * - * * @class * @memberof PIXI */ export class BufferSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'buffer', + }; + CONTEXT_UID: number; gl: IRenderingContext; @@ -55,9 +61,7 @@ export class BufferSystem implements ISystem this.renderer = null; } - /** - * Sets up the renderer context and necessary buffers. - */ + /** Sets up the renderer context and necessary buffers. */ protected contextChange(): void { this.disposeAll(true); @@ -70,7 +74,6 @@ export class BufferSystem implements ISystem /** * This binds specified buffer. On first run, it will create the webGL buffers for the context too - * * @param buffer - the buffer to bind to the renderer */ bind(buffer: Buffer): void @@ -86,7 +89,6 @@ export class BufferSystem implements ISystem * Binds an uniform buffer to at the given index. * * A cache is used so a buffer will not be bound again if already bound. - * * @param buffer - the buffer to bind * @param index - the base index to bind it to. */ @@ -107,7 +109,6 @@ export class BufferSystem implements ISystem /** * Binds a buffer whilst also binding its range. * This will make the buffer start from the offset supplied rather than 0 when it is read. - * * @param buffer - the buffer to bind * @param index - the base index to bind at, defaults to 0 * @param offset - the offset to bind at (this is blocks of 256). 0 = 0, 1 = 256, 2 = 512 etc @@ -125,7 +126,6 @@ export class BufferSystem implements ISystem /** * Will ensure the data in the buffer is uploaded to the GPU. - * * @param {PIXI.Buffer} buffer - the buffer to update */ update(buffer: Buffer): void @@ -205,6 +205,7 @@ export class BufferSystem implements ISystem /** * creates and attaches a GLBuffer object tied to the current context. + * @param buffer * @protected */ protected createGLBuffer(buffer: Buffer): GLBuffer @@ -220,3 +221,5 @@ export class BufferSystem implements ISystem return buffer._glBuffers[CONTEXT_UID]; } } + +extensions.add(BufferSystem); diff --git a/packages/core/src/geometry/Geometry.ts b/packages/core/src/geometry/Geometry.ts index dbc3e1478c0..9714aaac8f2 100644 --- a/packages/core/src/geometry/Geometry.ts +++ b/packages/core/src/geometry/Geometry.ts @@ -4,7 +4,8 @@ import { interleaveTypedArrays } from './utils/interleaveTypedArrays'; import { getBufferType } from '@pixi/utils'; import { Runner } from '@pixi/runner'; -import { BUFFER_TYPE, TYPES } from '@pixi/constants'; +import type { TYPES } from '@pixi/constants'; +import { BUFFER_TYPE } from '@pixi/constants'; import type { IArrayBuffer } from './Buffer'; import type { Dict } from '@pixi/utils'; @@ -37,7 +38,6 @@ const map: Dict = { * geometry.addAttribute('uvs', [0,0,1,0,1,1,0,1],2) * geometry.addIndex([0,1,2,1,3,2]) * ``` - * * @memberof PIXI */ export class Geometry @@ -52,14 +52,12 @@ export class Geometry /** * Number of instances in this geometry, pass it to `GeometrySystem.draw()`. - * * @default 1 */ public instanceCount: number; /** * A map of renderer IDs to webgl VAOs - * * @type {object} */ glVertexArrayObjects: {[key: number]: {[key: string]: WebGLVertexArrayObject}}; @@ -95,7 +93,6 @@ export class Geometry * * Adds an attribute to the geometry * Note: `stride` and `start` should be `undefined` if you dont know them, not 0! - * * @param id - the name of the attribute (matching up to a shader) * @param {PIXI.Buffer|number[]} buffer - the buffer that holds the data of the attribute . You can also provide an Array and a buffer will be created from it. * @param size - the size of the attribute. If you have 2 floats per vertex (eg position x and y) this would be 2 @@ -104,9 +101,9 @@ export class Geometry * @param [stride=0] - How far apart, in bytes, the start of each value is. (used for interleaving data) * @param [start=0] - How far into the array to start reading values (used for interleaving data) * @param instance - Instancing flag - * @return - Returns self, useful for chaining. + * @returns - Returns self, useful for chaining. */ - addAttribute(id: string, buffer: Buffer|Float32Array|Uint32Array|Array, size = 0, normalized = false, + addAttribute(id: string, buffer: Buffer | Float32Array | Uint32Array | Array, size = 0, normalized = false, type?: TYPES, stride?: number, start?: number, instance = false): this { if (!buffer) @@ -156,9 +153,8 @@ export class Geometry /** * Returns the requested attribute. - * * @param id - The name of the attribute required - * @return - The attribute requested. + * @returns - The attribute requested. */ getAttribute(id: string): Attribute { @@ -167,9 +163,8 @@ export class Geometry /** * Returns the requested buffer. - * * @param id - The name of the buffer required. - * @return - The buffer requested. + * @returns - The buffer requested. */ getBuffer(id: string): Buffer { @@ -177,13 +172,12 @@ export class Geometry } /** - * - * Adds an index buffer to the geometry - * The index buffer contains integers, three for each triangle in the geometry, which reference the various attribute buffers (position, colour, UV coordinates, other UV coordinates, normal, …). There is only ONE index buffer. - * - * @param {PIXI.Buffer|number[]} [buffer] - The buffer that holds the data of the index buffer. You can also provide an Array and a buffer will be created from it. - * @return - Returns self, useful for chaining. - */ + * + * Adds an index buffer to the geometry + * The index buffer contains integers, three for each triangle in the geometry, which reference the various attribute buffers (position, colour, UV coordinates, other UV coordinates, normal, …). There is only ONE index buffer. + * @param {PIXI.Buffer|number[]} [buffer] - The buffer that holds the data of the index buffer. You can also provide an Array and a buffer will be created from it. + * @returns - Returns self, useful for chaining. + */ addIndex(buffer?: Buffer | IArrayBuffer | number[]): Geometry { if (!(buffer instanceof Buffer)) @@ -201,7 +195,7 @@ export class Geometry this.indexBuffer = buffer; - if (this.buffers.indexOf(buffer) === -1) + if (!this.buffers.includes(buffer)) { this.buffers.push(buffer); } @@ -211,8 +205,7 @@ export class Geometry /** * Returns the index buffer - * - * @return - The index buffer. + * @returns - The index buffer. */ getIndex(): Buffer { @@ -222,8 +215,7 @@ export class Geometry /** * This function modifies the structure so that all current attributes become interleaved into a single buffer * This can be useful if your model remains static as it offers a little performance boost - * - * @return - Returns self, useful for chaining. + * @returns - Returns self, useful for chaining. */ interleave(): Geometry { @@ -301,7 +293,6 @@ export class Geometry /** * Returns a clone of the geometry. - * * @returns - A new clone of this geometry. */ clone(): Geometry @@ -341,9 +332,8 @@ export class Geometry * Merges an array of geometries into a new single one. * * Geometry attribute styles must match for this operation to work. - * * @param geometries - array of geometries to merge - * @return - Shiny new geometry! + * @returns - Shiny new geometry! */ static merge(geometries: Array): Geometry { diff --git a/packages/core/src/geometry/GeometrySystem.ts b/packages/core/src/geometry/GeometrySystem.ts index cbcc41a993c..497743d552e 100644 --- a/packages/core/src/geometry/GeometrySystem.ts +++ b/packages/core/src/geometry/GeometrySystem.ts @@ -1,42 +1,46 @@ -import { GLBuffer } from './GLBuffer'; +import type { GLBuffer } from './GLBuffer'; import { ENV } from '@pixi/constants'; import { settings } from '../settings'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { DRAW_MODES } from '@pixi/constants'; import type { Renderer } from '../Renderer'; -import type { IRenderingContext } from '../IRenderingContext'; import type { Geometry } from './Geometry'; import type { Shader } from '../shader/Shader'; import type { Program } from '../shader/Program'; import type { Dict } from '@pixi/utils'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; const byteSizeMap: {[key: number]: number} = { 5126: 4, 5123: 2, 5121: 1 }; /** * System plugin to the renderer to manage geometry. - * * @memberof PIXI */ export class GeometrySystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'geometry', + }; + /** * `true` if we has `*_vertex_array_object` extension. - * * @readonly */ public hasVao: boolean; /** * `true` if has `ANGLE_instanced_arrays` extension. - * * @readonly */ public hasInstance: boolean; /** * `true` if support `gl.UNSIGNED_INT` in `gl.drawElements` or `gl.drawElementsInstanced`. - * * @readonly */ public canUseUInt32ElementIndex: boolean; @@ -138,7 +142,6 @@ export class GeometrySystem implements ISystem /** * Binds geometry so that is can be drawn. Creating a Vao if required - * * @param geometry - Instance of geometry to bind. * @param shader - Instance of shader to use vao for. */ @@ -210,7 +213,6 @@ export class GeometrySystem implements ISystem /** * Check compatibility between a geometry and a program - * * @param geometry - Geometry instance. * @param program - Program instance. */ @@ -231,10 +233,9 @@ export class GeometrySystem implements ISystem /** * Takes a geometry and program and generates a unique signature for them. - * * @param geometry - To get signature from. * @param program - To test geometry against. - * @return - Unique signature of the geometry and program + * @returns - Unique signature of the geometry and program */ protected getSignature(geometry: Geometry, program: Program): string { @@ -258,7 +259,6 @@ export class GeometrySystem implements ISystem * Creates or gets Vao with the same structure as the geometry and stores it on the geometry. * If vao is created, it is bound automatically. We use a shader to infer what and how to set up the * attribute locations. - * * @param geometry - Instance of geometry to to generate Vao for. * @param shader - Instance of the shader. * @param incRefCount - Increment refCount of all geometry buffers. @@ -375,7 +375,6 @@ export class GeometrySystem implements ISystem /** * Disposes geometry. - * * @param geometry - Geometry with buffers. Only VAO will be disposed * @param [contextLost=false] - If context was lost, we suppress deleteVertexArray */ @@ -444,7 +443,6 @@ export class GeometrySystem implements ISystem /** * Dispose all WebGL resources of all managed geometries. - * * @param [contextLost=false] - If context was lost, we suppress `gl.delete` calls */ disposeAll(contextLost?: boolean): void @@ -459,7 +457,6 @@ export class GeometrySystem implements ISystem /** * Activate vertex array object. - * * @param geometry - Geometry instance. * @param program - Shader program instance. */ @@ -526,7 +523,6 @@ export class GeometrySystem implements ISystem /** * Draws the currently bound geometry. - * * @param type - The type primitive to render. * @param size - The number of elements to be rendered. If not specified, all vertices after the * starting vertex will be drawn. @@ -593,3 +589,5 @@ export class GeometrySystem implements ISystem this.renderer = null; } } + +extensions.add(GeometrySystem); diff --git a/packages/core/src/geometry/ViewableBuffer.ts b/packages/core/src/geometry/ViewableBuffer.ts index 7f212666db4..8912f4fcb68 100644 --- a/packages/core/src/geometry/ViewableBuffer.ts +++ b/packages/core/src/geometry/ViewableBuffer.ts @@ -2,7 +2,6 @@ import type { ITypedArray } from './Buffer'; /** * Flexible wrapper around `ArrayBuffer` that also provides typed array views on demand. - * * @memberof PIXI */ export class ViewableBuffer @@ -110,10 +109,9 @@ export class ViewableBuffer /** * Returns the view of the given type. - * * @param type - One of `int8`, `uint8`, `int16`, * `uint16`, `int32`, `uint32`, and `float32`. - * @return - typed array of given type + * @returns - typed array of given type */ view(type: string): ITypedArray { diff --git a/packages/core/src/geometry/utils/setVertexAttribArrays.ts b/packages/core/src/geometry/utils/setVertexAttribArrays.ts index ddc09562a90..b370eb639cb 100644 --- a/packages/core/src/geometry/utils/setVertexAttribArrays.ts +++ b/packages/core/src/geometry/utils/setVertexAttribArrays.ts @@ -1,5 +1,5 @@ -import type { IRenderingContext } from '../../IRenderingContext'; import type { Dict } from '@pixi/utils'; +import type { IRenderingContext } from '../../IRenderer'; // var GL_MAP = {}; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index d7cac71bf82..c410632c65f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,14 +1,35 @@ import './settings'; +/** + * @namespace PIXI + */ + +/** + * String of the current PIXI version. + * @memberof PIXI + */ +export const VERSION = '$_VERSION'; + +/** Export dependencies */ +export * from '@pixi/constants'; +export * from '@pixi/extensions'; +export * from '@pixi/math'; +export * from '@pixi/runner'; +export * from '@pixi/settings'; +export * from '@pixi/ticker'; +import * as utils from '@pixi/utils'; +export { utils }; + export * from './textures/resources'; export * from './systems'; -export * from './IRenderingContext'; -export * from './IRenderableObject'; +export * from './IRenderer'; + export * from './autoDetectRenderer'; export * from './fragments'; -export * from './ISystem'; +export * from './system/ISystem'; +export * from './IRenderer'; +export * from './plugin/PluginSystem'; export * from './Renderer'; -export * from './AbstractRenderer'; export * from './framebuffer/Framebuffer'; export * from './framebuffer/GLFramebuffer'; export * from './textures/Texture'; @@ -21,8 +42,7 @@ export * from './renderTexture/BaseRenderTexture'; export * from './textures/TextureUvs'; export * from './state/State'; export * from './batch/ObjectRenderer'; -export * from './batch/AbstractBatchRenderer'; -export * from './batch/BatchPluginFactory'; +export * from './batch/BatchRenderer'; export * from './batch/BatchShaderGenerator'; export * from './batch/BatchGeometry'; export * from './batch/BatchDrawCall'; @@ -47,4 +67,27 @@ export * from './geometry/Attribute'; export * from './geometry/Buffer'; export * from './geometry/Geometry'; export * from './geometry/ViewableBuffer'; -export * from './deprecations'; + +export * from './mask/MaskSystem'; +export * from './mask/StencilSystem'; +export * from './mask/ScissorSystem'; +export * from './filters/FilterSystem'; +export * from './framebuffer/FramebufferSystem'; +export * from './renderTexture/RenderTextureSystem'; +export * from './textures/TextureSystem'; +export * from './projection/ProjectionSystem'; +export * from './state/StateSystem'; +export * from './geometry/GeometrySystem'; +export * from './shader/ShaderSystem'; +export * from './context/ContextSystem'; +export * from './batch/BatchSystem'; +export * from './textures/TextureGCSystem'; +export * from './geometry/BufferSystem'; +export * from './plugin/PluginSystem'; +export * from './framebuffer/MultisampleSystem'; +export * from './renderTexture/GenerateTextureSystem'; +export * from './renderTexture/GenerateTextureSystem'; +export * from './background/BackgroundSystem'; +export * from './view/ViewSystem'; +export * from './render/ObjectRendererSystem'; +export * from './startup/StartupSystem'; diff --git a/packages/core/src/mask/AbstractMaskSystem.ts b/packages/core/src/mask/AbstractMaskSystem.ts index 0aedd39d01a..d97c4d4aad4 100644 --- a/packages/core/src/mask/AbstractMaskSystem.ts +++ b/packages/core/src/mask/AbstractMaskSystem.ts @@ -1,10 +1,9 @@ -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { MaskData } from './MaskData'; import type { Renderer } from '../Renderer'; /** * System plugin to the renderer to manage specific types of masking operations. - * * @memberof PIXI */ export class AbstractMaskSystem implements ISystem @@ -41,7 +40,6 @@ export class AbstractMaskSystem implements ISystem /** * Changes the mask stack that is used by this System. - * * @param {PIXI.MaskData[]} maskStack - The mask stack */ setMaskStack(maskStack: Array): void diff --git a/packages/core/src/mask/MaskData.ts b/packages/core/src/mask/MaskData.ts index 5d5c5c4388e..beadf01d5ff 100644 --- a/packages/core/src/mask/MaskData.ts +++ b/packages/core/src/mask/MaskData.ts @@ -1,7 +1,8 @@ -import { MASK_TYPES, MSAA_QUALITY } from '@pixi/constants'; +import { MASK_TYPES } from '@pixi/constants'; import { settings } from '@pixi/settings'; -import { ISpriteMaskFilter } from '@pixi/core'; +import type { ISpriteMaskFilter } from '@pixi/core'; +import type { COLOR_MASK_BITS, MSAA_QUALITY } from '@pixi/constants'; import type { Rectangle, Matrix } from '@pixi/math'; import type { IFilterTarget } from '../filters/IFilterTarget'; import type { Renderer } from '../Renderer'; @@ -12,14 +13,13 @@ export interface IMaskTarget extends IFilterTarget isSprite?: boolean; worldTransform: Matrix; isFastRect?(): boolean; - getBounds(skipUpdate?: boolean): Rectangle; + getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle; render(renderer: Renderer): void; } /** * Component for masked elements. * * Holds mask mode and temporary data about current mask. - * * @memberof PIXI */ export class MaskData @@ -62,6 +62,9 @@ export class MaskData /** If enabled is true the mask is applied, if false it will not. */ public enabled: boolean; + /** Color mask. */ + public colorMask: COLOR_MASK_BITS; + /** * The sprite mask filter wrapped in an array. * @private @@ -83,15 +86,23 @@ export class MaskData /** * Scissor operation above the mask in stack. * Null if _scissorCounter is zero, rectangle instance if positive. + * @private */ _scissorRect: Rectangle; /** * pre-computed scissor rect * does become _scissorRect when mask is actually pushed + * @private */ _scissorRectLocal: Rectangle; + /** + * pre-computed color mask + * @private + */ + _colorMask: number; + /** * Targeted element. Temporary variable set by MaskSystem * @member {PIXI.DisplayObject} @@ -101,7 +112,6 @@ export class MaskData /** * Create MaskData - * * @param {PIXI.DisplayObject} [maskObject=null] - object that describes the mask */ constructor(maskObject: IMaskTarget = null) @@ -114,11 +124,13 @@ export class MaskData this.resolution = null; this.multisample = settings.FILTER_MULTISAMPLE; this.enabled = true; + this.colorMask = 0xf; this._filters = null; this._stencilCounter = 0; this._scissorCounter = 0; this._scissorRect = null; this._scissorRectLocal = null; + this._colorMask = 0xf; this._target = null; } @@ -167,7 +179,10 @@ export class MaskData this._scissorRectLocal = null; } - /** Copies counters from maskData above, called from pushMask(). */ + /** + * Copies counters from maskData above, called from pushMask(). + * @param maskAbove + */ copyCountersOrReset(maskAbove?: MaskData): void { if (maskAbove) diff --git a/packages/core/src/mask/MaskSystem.ts b/packages/core/src/mask/MaskSystem.ts index dc175200c2a..1cbc13c8c4c 100644 --- a/packages/core/src/mask/MaskSystem.ts +++ b/packages/core/src/mask/MaskSystem.ts @@ -2,20 +2,22 @@ import { MaskData } from './MaskData'; import { SpriteMaskFilter } from '../filters/spriteMask/SpriteMaskFilter'; import { MASK_TYPES } from '@pixi/constants'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { IMaskTarget } from './MaskData'; import type { Renderer } from '../Renderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * System plugin to the renderer to manage masks. * * There are three built-in types of masking: - * * **Scissor Masking**: Scissor masking discards pixels that are outside of a rectangle called the scissor box. It is + * **Scissor Masking**: Scissor masking discards pixels that are outside of a rectangle called the scissor box. It is * the most performant as the scissor test is inexpensive. However, it can only be used when the mask is rectangular. - * * **Stencil Masking**: Stencil masking discards pixels that don't overlap with the pixels rendered into the stencil + * **Stencil Masking**: Stencil masking discards pixels that don't overlap with the pixels rendered into the stencil * buffer. It is the next fastest option as it does not require rendering into a separate framebuffer. However, it does * cause the mask to be rendered **twice** for each masking operation; hence, minimize the rendering cost of your masks. - * * **Sprite Mask Filtering**: Sprite mask filtering discards pixels based on the red channel of the sprite-mask's + * **Sprite Mask Filtering**: Sprite mask filtering discards pixels based on the red channel of the sprite-mask's * texture. (Generally, the masking texture is grayscale). Using advanced techniques, you might be able to embed this * type of masking in a custom shader - and hence, bypassing the masking system fully for performance wins. * @@ -27,14 +29,18 @@ import type { Renderer } from '../Renderer'; * In the scene graph, masks can be applied recursively, i.e. a mask can be applied during a masking operation. The mask * stack stores the currently applied masks in order. Each {@link PIXI.BaseRenderTexture} holds its own mask stack, i.e. * when you switch render-textures, the old masks only applied when you switch back to rendering to the old render-target. - * * @memberof PIXI */ export class MaskSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'mask', + }; + /** * Flag to enable scissor masking. - * * @default true */ public enableScissor: boolean; @@ -71,7 +77,6 @@ export class MaskSystem implements ISystem /** * Changes the mask stack that is used by this System. - * * @param maskStack - The mask stack */ setMaskStack(maskStack: Array): void @@ -85,11 +90,10 @@ export class MaskSystem implements ISystem * Enables the mask and appends it to the current mask stack. * * NOTE: The batch renderer should be flushed beforehand to prevent pending renders from being masked. - * * @param {PIXI.DisplayObject} target - Display Object to push the mask to - * @param {PIXI.MaskData|PIXI.Sprite|PIXI.Graphics|PIXI.DisplayObject} maskData - The masking data. + * @param {PIXI.MaskData|PIXI.Sprite|PIXI.Graphics|PIXI.DisplayObject} maskDataOrTarget - The masking data. */ - push(target: IMaskTarget, maskDataOrTarget: MaskData|IMaskTarget): void + push(target: IMaskTarget, maskDataOrTarget: MaskData | IMaskTarget): void { let maskData = maskDataOrTarget as MaskData; @@ -105,6 +109,7 @@ export class MaskSystem implements ISystem const maskAbove = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null; maskData.copyCountersOrReset(maskAbove); + maskData._colorMask = maskAbove ? maskAbove._colorMask : 0xf; if (maskData.autoDetect) { @@ -132,6 +137,9 @@ export class MaskSystem implements ISystem maskData.copyCountersOrReset(null); this.pushSpriteMask(maskData); break; + case MASK_TYPES.COLOR: + this.pushColorMask(maskData); + break; default: break; } @@ -147,8 +155,7 @@ export class MaskSystem implements ISystem * Removes the last mask from the mask stack and doesn't return it. * * NOTE: The batch renderer should be flushed beforehand to render the masked contents before the mask is removed. - * - * @param {PIXI.DisplayObject} target - Display Object to pop the mask from + * @param {PIXI.IMaskTarget} target - Display Object to pop the mask from */ pop(target: IMaskTarget): void { @@ -166,7 +173,7 @@ export class MaskSystem implements ISystem switch (maskData.type) { case MASK_TYPES.SCISSOR: - this.renderer.scissor.pop(); + this.renderer.scissor.pop(maskData); break; case MASK_TYPES.STENCIL: this.renderer.stencil.pop(maskData.maskObject); @@ -174,6 +181,9 @@ export class MaskSystem implements ISystem case MASK_TYPES.SPRITE: this.popSpriteMask(maskData); break; + case MASK_TYPES.COLOR: + this.popColorMask(maskData); + break; default: break; } @@ -197,12 +207,19 @@ export class MaskSystem implements ISystem } } - /** Sets type of MaskData based on its maskObject. */ + /** + * Sets type of MaskData based on its maskObject. + * @param maskData + */ detect(maskData: MaskData): void { const maskObject = maskData.maskObject; - if (maskObject.isSprite) + if (!maskObject) + { + maskData.type = MASK_TYPES.COLOR; + } + else if (maskObject.isSprite) { maskData.type = MASK_TYPES.SPRITE; } @@ -218,7 +235,6 @@ export class MaskSystem implements ISystem /** * Applies the Mask and adds it to the current filter stack. - * * @param maskData - Sprite to be used as the mask. */ pushSpriteMask(maskData: MaskData): void @@ -274,7 +290,6 @@ export class MaskSystem implements ISystem /** * Removes the last filter from the filter stack and doesn't return it. - * * @param maskData - Sprite to be used as the mask. */ popSpriteMask(maskData: MaskData): void @@ -292,8 +307,51 @@ export class MaskSystem implements ISystem } } + /** + * Pushes the color mask. + * @param maskData - The mask data + */ + pushColorMask(maskData: MaskData): void + { + const currColorMask = maskData._colorMask; + const nextColorMask = maskData._colorMask = currColorMask & maskData.colorMask; + + if (nextColorMask !== currColorMask) + { + this.renderer.gl.colorMask( + (nextColorMask & 0x1) !== 0, + (nextColorMask & 0x2) !== 0, + (nextColorMask & 0x4) !== 0, + (nextColorMask & 0x8) !== 0 + ); + } + } + + /** + * Pops the color mask. + * @param maskData - The mask data + */ + popColorMask(maskData: MaskData): void + { + const currColorMask = maskData._colorMask; + const nextColorMask = this.maskStack.length > 0 + ? this.maskStack[this.maskStack.length - 1]._colorMask : 0xf; + + if (nextColorMask !== currColorMask) + { + this.renderer.gl.colorMask( + (nextColorMask & 0x1) !== 0, + (nextColorMask & 0x2) !== 0, + (nextColorMask & 0x4) !== 0, + (nextColorMask & 0x8) !== 0 + ); + } + } + destroy(): void { this.renderer = null; } } + +extensions.add(MaskSystem); diff --git a/packages/core/src/mask/ScissorSystem.ts b/packages/core/src/mask/ScissorSystem.ts index dbe3d45d502..d0c0e8d5927 100644 --- a/packages/core/src/mask/ScissorSystem.ts +++ b/packages/core/src/mask/ScissorSystem.ts @@ -3,8 +3,12 @@ import { AbstractMaskSystem } from './AbstractMaskSystem'; import type { Renderer } from '../Renderer'; import type { MaskData } from './MaskData'; import { Matrix, Rectangle } from '@pixi/math'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import { settings } from '@pixi/settings'; const tempMatrix = new Matrix(); +const rectPool: Rectangle[] = []; /** * System plugin to the renderer to manage scissor masking. @@ -12,11 +16,16 @@ const tempMatrix = new Matrix(); * Scissor masking discards pixels outside of a rectangle called the scissor box. The scissor box is in the framebuffer * viewport's space; however, the mask's rectangle is projected from world-space to viewport space automatically * by this system. - * * @memberof PIXI */ export class ScissorSystem extends AbstractMaskSystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'scissor', + }; + /** * @param {PIXI.Renderer} renderer - The renderer this System works for. */ @@ -24,7 +33,7 @@ export class ScissorSystem extends AbstractMaskSystem { super(renderer); - this.glConst = WebGLRenderingContext.SCISSOR_TEST; + this.glConst = settings.ADAPTER.getWebGLRenderingContext().SCISSOR_TEST; } getStackLength(): number @@ -54,10 +63,7 @@ export class ScissorSystem extends AbstractMaskSystem const { maskObject } = maskData; const { renderer } = this; const renderTextureSystem = renderer.renderTexture; - - maskObject.renderable = true; - - const rect = maskObject.getBounds(); + const rect = maskObject.getBounds(true, rectPool.pop() ?? new Rectangle()); this.roundFrameToPixels(rect, renderTextureSystem.current ? renderTextureSystem.current.resolution : renderer.resolution, @@ -65,8 +71,6 @@ export class ScissorSystem extends AbstractMaskSystem renderTextureSystem.destinationFrame, renderer.projection.transform); - maskObject.renderable = false; - if (prevData) { rect.fit(prevData); @@ -91,7 +95,7 @@ export class ScissorSystem extends AbstractMaskSystem /** * Test, whether the object can be scissor mask with current renderer projection. * Calls "calcScissorRect()" if its true. - * @param maskData mask data + * @param maskData - mask data * @returns whether Whether the object can be scissor mask */ public testScissor(maskData: MaskData): boolean @@ -153,7 +157,6 @@ export class ScissorSystem extends AbstractMaskSystem /** * Applies the Mask and adds it to the current stencil stack. - * * @author alvin * @param maskData - The mask data. */ @@ -181,11 +184,17 @@ export class ScissorSystem extends AbstractMaskSystem * last mask in the stack. * * This can also be called when you directly modify the scissor box and want to restore PixiJS state. + * @param maskData - The mask data. */ - pop(): void + pop(maskData?: MaskData): void { const { gl } = this.renderer; + if (maskData) + { + rectPool.push(maskData._scissorRectLocal); + } + if (this.getStackLength() > 0) { this._useCurrent(); @@ -218,3 +227,5 @@ export class ScissorSystem extends AbstractMaskSystem this.renderer.gl.scissor(rect.x, y, rect.width, rect.height); } } + +extensions.add(ScissorSystem); diff --git a/packages/core/src/mask/StencilSystem.ts b/packages/core/src/mask/StencilSystem.ts index dcf8fddfee1..d943b627299 100644 --- a/packages/core/src/mask/StencilSystem.ts +++ b/packages/core/src/mask/StencilSystem.ts @@ -2,14 +2,22 @@ import { AbstractMaskSystem } from './AbstractMaskSystem'; import type { Renderer } from '../Renderer'; import type { IMaskTarget, MaskData } from './MaskData'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import { settings } from '@pixi/settings'; /** * System plugin to the renderer to manage stencils (used for masks). - * * @memberof PIXI */ export class StencilSystem extends AbstractMaskSystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'stencil', + }; + /** * @param renderer - The renderer this System works for. */ @@ -17,7 +25,7 @@ export class StencilSystem extends AbstractMaskSystem { super(renderer); - this.glConst = WebGLRenderingContext.STENCIL_TEST; + this.glConst = settings.ADAPTER.getWebGLRenderingContext().STENCIL_TEST; } getStackLength(): number @@ -34,7 +42,6 @@ export class StencilSystem extends AbstractMaskSystem /** * Applies the Mask and adds it to the current stencil stack. - * * @param maskData - The mask data */ push(maskData: MaskData): void @@ -54,8 +61,15 @@ export class StencilSystem extends AbstractMaskSystem maskData._stencilCounter++; + const colorMask = maskData._colorMask; + + if (colorMask !== 0) + { + maskData._colorMask = 0; + gl.colorMask(false, false, false, false); + } + // Increment the reference stencil value where the new mask overlaps with the old ones. - gl.colorMask(false, false, false, false); gl.stencilFunc(gl.EQUAL, prevMaskCount, 0xFFFFFFFF); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); @@ -64,12 +78,22 @@ export class StencilSystem extends AbstractMaskSystem this.renderer.batch.flush(); maskObject.renderable = false; + if (colorMask !== 0) + { + maskData._colorMask = colorMask; + gl.colorMask( + (colorMask & 1) !== 0, + (colorMask & 2) !== 0, + (colorMask & 4) !== 0, + (colorMask & 8) !== 0 + ); + } + this._useCurrent(); } /** * Pops stencil mask. MaskData is already removed from stack - * * @param {PIXI.DisplayObject} maskObject - object of popped mask data */ pop(maskObject: IMaskTarget): void @@ -83,8 +107,16 @@ export class StencilSystem extends AbstractMaskSystem } else { + const maskData = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null; + const colorMask = maskData ? maskData._colorMask : 0xf; + + if (colorMask !== 0) + { + maskData._colorMask = 0; + gl.colorMask(false, false, false, false); + } + // Decrement the reference stencil value where the popped mask overlaps with the other ones - gl.colorMask(false, false, false, false); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); maskObject.renderable = true; @@ -92,6 +124,17 @@ export class StencilSystem extends AbstractMaskSystem this.renderer.batch.flush(); maskObject.renderable = false; + if (colorMask !== 0) + { + maskData._colorMask = colorMask; + gl.colorMask( + (colorMask & 0x1) !== 0, + (colorMask & 0x2) !== 0, + (colorMask & 0x4) !== 0, + (colorMask & 0x8) !== 0 + ); + } + this._useCurrent(); } } @@ -104,8 +147,9 @@ export class StencilSystem extends AbstractMaskSystem { const gl = this.renderer.gl; - gl.colorMask(true, true, true, true); gl.stencilFunc(gl.EQUAL, this.getStackLength(), 0xFFFFFFFF); gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); } } + +extensions.add(StencilSystem); diff --git a/packages/core/src/plugin/PluginSystem.ts b/packages/core/src/plugin/PluginSystem.ts new file mode 100644 index 00000000000..a38dfeb2e15 --- /dev/null +++ b/packages/core/src/plugin/PluginSystem.ts @@ -0,0 +1,102 @@ +import { deprecation } from '@pixi/utils'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { IRenderer } from '../IRenderer'; +import type { ISystem } from '../system/ISystem'; + +export interface IRendererPlugins extends GlobalMixins.IRendererPlugins +{ + [key: string]: any; +} + +/** + * Manages the functionality that allows users to extend pixi functionality via additional plugins. + * @memberof PIXI + */ +export class PluginSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + name: '_plugin', + }; + + /** + * Collection of plugins. + * @readonly + * @member {object} + */ + public readonly plugins: IRendererPlugins; + private renderer: IRenderer; + + constructor(renderer: IRenderer) + { + this.renderer = renderer; + + /** + * Collection of plugins. + * @readonly + * @member {object} + */ + this.plugins = {}; + + // #if _DEBUG + Object.defineProperties(this.plugins, { + extract: { + enumerable: false, + get() + { + deprecation('7.0.0', 'renderer.plugins.extract has moved to renderer.extract'); + + return (renderer as any).extract; + }, + }, + prepare: { + enumerable: false, + get() + { + deprecation('7.0.0', 'renderer.plugins.prepare has moved to renderer.prepare'); + + return (renderer as any).prepare; + }, + }, + interaction: { + enumerable: false, + get() + { + deprecation('7.0.0', 'renderer.plugins.interaction has been deprecated, use renderer.events'); + + return (renderer as any).events; + }, + }, + }); + // #endif + } + + /** + * Initialize the plugins. + * @protected + * @param {object} staticMap - The dictionary of statically saved plugins. + */ + init(staticMap: IRendererPlugins): void + { + for (const o in staticMap) + { + this.plugins[o] = new (staticMap[o])(this.renderer); + } + } + + destroy(): void + { + for (const o in this.plugins) + { + this.plugins[o].destroy(); + this.plugins[o] = null; + } + } +} + +extensions.add(PluginSystem); diff --git a/packages/core/src/projection/ProjectionSystem.ts b/packages/core/src/projection/ProjectionSystem.ts index eea9e1cb83f..7478a68ba0d 100644 --- a/packages/core/src/projection/ProjectionSystem.ts +++ b/packages/core/src/projection/ProjectionSystem.ts @@ -1,19 +1,26 @@ import { Matrix } from '@pixi/math'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Rectangle } from '@pixi/math'; import type { Renderer } from '../Renderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * System plugin to the renderer to manage the projection matrix. * * The `projectionMatrix` is a global uniform provided to all shaders. It is used to transform points in world space to * normalized device coordinates. - * * @memberof PIXI */ export class ProjectionSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'projection', + }; + /** * The destination frame used to calculate the current projection matrix. * @@ -28,7 +35,6 @@ export class ProjectionSystem implements ISystem * The destination frame's dimensions (width,height) should be equal to the source frame. This is because, * otherwise, the contents will be scaled to fill the destination frame. Similarly, the destination frame's (x,y) * coordinates are (0,0) unless you know what you're doing. - * * @readonly */ public destinationFrame: Rectangle; @@ -37,7 +43,6 @@ export class ProjectionSystem implements ISystem * The source frame used to calculate the current projection matrix. * * The source frame is the rectangle in world space containing the contents to be rendered. - * * @readonly */ public sourceFrame: Rectangle; @@ -47,7 +52,6 @@ export class ProjectionSystem implements ISystem * * This is not used internally. It is not advised to use this feature specifically unless you know what * you're doing. The `update` method will default to this frame if you do not pass the destination frame. - * * @readonly */ public defaultFrame: Rectangle; @@ -60,7 +64,6 @@ export class ProjectionSystem implements ISystem * * The renderer's `globalUniforms` keeps a reference to this, and so it is available for all shaders to use as a * uniform. - * * @readonly */ public projectionMatrix: Matrix; @@ -70,7 +73,6 @@ export class ProjectionSystem implements ISystem * * This can be used to transform points in world-space one last time before they are outputted by the shader. You can * use to rotate the whole scene, for example. Remember to clear it once you've rendered everything. - * * @member {PIXI.Matrix} */ public transform: Matrix; @@ -97,7 +99,6 @@ export class ProjectionSystem implements ISystem * * NOTE-2: {@link RenderTextureSystem#bind} updates the projection-matrix when you bind a render-texture. It is expected * that you dirty the current bindings when calling this manually. - * * @param destinationFrame - The rectangle in the render-target to render the contents into. If rendering to the canvas, * the origin is on the top-left; if rendering to a render-texture, the origin is on the bottom-left. * @param sourceFrame - The rectangle in world space that contains the contents being rendered. @@ -134,10 +135,9 @@ export class ProjectionSystem implements ISystem /** * Calculates the `projectionMatrix` to map points inside `sourceFrame` to inside `destinationFrame`. - * - * @param destinationFrame - The destination frame in the render-target. + * @param _destinationFrame - The destination frame in the render-target. * @param sourceFrame - The source frame in world space. - * @param resolution - The render-target's resolution, i.e. ratio of CSS to physical pixels. + * @param _resolution - The render-target's resolution, i.e. ratio of CSS to physical pixels. * @param root - Whether rendering into the screen. Otherwise, if rendering to a framebuffer, the projection * is y-flipped. */ @@ -157,8 +157,7 @@ export class ProjectionSystem implements ISystem /** * Sets the transform of the active render target to the given matrix. - * - * @param matrix - The transformation matrix + * @param _matrix - The transformation matrix */ setTransform(_matrix: Matrix): void { @@ -170,3 +169,5 @@ export class ProjectionSystem implements ISystem this.renderer = null; } } + +extensions.add(ProjectionSystem); diff --git a/packages/core/src/render/ObjectRendererSystem.ts b/packages/core/src/render/ObjectRendererSystem.ts new file mode 100644 index 00000000000..068eaa75fcd --- /dev/null +++ b/packages/core/src/render/ObjectRendererSystem.ts @@ -0,0 +1,134 @@ +import type { Matrix } from '@pixi/math'; +import type { IRenderableObject, IRendererRenderOptions } from '../IRenderer'; +import type { ISystem } from '../system/ISystem'; +import type { Renderer } from '../Renderer'; +import type { RenderTexture } from '../renderTexture/RenderTexture'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; + +/** + * system that provides a render function that focussing on rendering Pixi Scene Graph objects + * to either the main view or to a renderTexture. Used for Canvas `WebGL` contexts + * @memberof PIXI + */ +export class ObjectRendererSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'objectRenderer', + }; + + renderer: Renderer; + + /** + * Flag if we are rendering to the screen vs renderTexture + * @readonly + * @default true + */ + renderingToScreen: boolean; + + /** + * the last object rendered by the renderer. Useful for other plugins like interaction managers + * @readonly + */ + lastObjectRendered: IRenderableObject; + + // renderers scene graph! + constructor(renderer: Renderer) + { + this.renderer = renderer; + } + + /** + * Renders the object to its WebGL view. + * @param displayObject - The object to be rendered. + * @param options - the options to be passed to the renderer + */ + render(displayObject: IRenderableObject, options?: IRendererRenderOptions): void + { + const renderer = this.renderer; + + let renderTexture: RenderTexture; + let clear: boolean; + let transform: Matrix; + let skipUpdateTransform: boolean; + + if (options) + { + renderTexture = options.renderTexture; + clear = options.clear; + transform = options.transform; + skipUpdateTransform = options.skipUpdateTransform; + } + + // can be handy to know! + this.renderingToScreen = !renderTexture; + + renderer.runners.prerender.emit(); + renderer.emit('prerender'); + + // apply a transform at a GPU level + renderer.projection.transform = transform; + + // no point rendering if our context has been blown up! + if (renderer.context.isLost) + { + return; + } + + if (!renderTexture) + { + this.lastObjectRendered = displayObject; + } + + if (!skipUpdateTransform) + { + // update the scene graph + const cacheParent = displayObject.enableTempParent(); + + displayObject.updateTransform(); + displayObject.disableTempParent(cacheParent); + // displayObject.hitArea = //TODO add a temp hit area + } + + renderer.renderTexture.bind(renderTexture); + renderer.batch.currentRenderer.start(); + + if (clear ?? renderer.background.clearBeforeRender) + { + renderer.renderTexture.clear(); + } + + displayObject.render(renderer); + + // apply transform.. + renderer.batch.currentRenderer.flush(); + + if (renderTexture) + { + if (options.blit) + { + renderer.framebuffer.blit(); + } + + renderTexture.baseTexture.update(); + } + + renderer.runners.postrender.emit(); + + // reset transform after render + renderer.projection.transform = null; + + renderer.emit('postrender'); + } + + destroy(): void + { + // ka pow! + this.renderer = null; + this.lastObjectRendered = null; + } +} + +extensions.add(ObjectRendererSystem); diff --git a/packages/core/src/renderTexture/BaseRenderTexture.ts b/packages/core/src/renderTexture/BaseRenderTexture.ts index bc221ce3fb0..60a258e75a4 100644 --- a/packages/core/src/renderTexture/BaseRenderTexture.ts +++ b/packages/core/src/renderTexture/BaseRenderTexture.ts @@ -42,7 +42,6 @@ export interface BaseRenderTexture extends GlobalMixins.BaseRenderTexture, BaseT * * renderer.render(sprite, {renderTexture}); // Renders to center of RenderTexture * ``` - * * @memberof PIXI */ export class BaseRenderTexture extends BaseTexture @@ -83,7 +82,7 @@ export class BaseRenderTexture extends BaseTexture options.width = options.width || 100; options.height = options.height || 100; - options.multisample = options.multisample !== undefined ? options.multisample : MSAA_QUALITY.NONE; + options.multisample ??= MSAA_QUALITY.NONE; super(null, options); @@ -104,7 +103,6 @@ export class BaseRenderTexture extends BaseTexture /** * Resizes the BaseRenderTexture. - * * @param desiredWidth - The desired width to resize to. * @param desiredHeight - The desired height to resize to. */ @@ -118,7 +116,6 @@ export class BaseRenderTexture extends BaseTexture * Frees the texture and framebuffer from WebGL memory without destroying this texture object. * This means you can still use the texture later which will upload it to GPU * memory again. - * * @fires PIXI.BaseTexture#dispose */ dispose(): void diff --git a/packages/core/src/renderTexture/GenerateTextureSystem.ts b/packages/core/src/renderTexture/GenerateTextureSystem.ts new file mode 100644 index 00000000000..87e8dff101c --- /dev/null +++ b/packages/core/src/renderTexture/GenerateTextureSystem.ts @@ -0,0 +1,103 @@ +import type { MSAA_QUALITY, SCALE_MODES } from '@pixi/constants'; +import type { Rectangle } from '@pixi/math'; +import { Matrix, Transform } from '@pixi/math'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { IRenderer, IRenderableContainer, IRenderableObject } from '../IRenderer'; +import type { ISystem } from '../system/ISystem'; +import { RenderTexture } from './RenderTexture'; + +const tempTransform = new Transform(); + +// TODO could this just be part of extract? +export interface IGenerateTextureOptions +{ + /** The scale mode of the texture. Optional, defaults to `PIXI.settings.SCALE_MODE`. */ + scaleMode?: SCALE_MODES; + /** The resolution / device pixel ratio of the texture being generated. Optional defaults to Renderer resolution. */ + resolution?: number; + /** + * The region of the displayObject, that shall be rendered, + * if no region is specified, defaults to the local bounds of the displayObject. + */ + region?: Rectangle; + /** The number of samples of the frame buffer. */ + multisample?: MSAA_QUALITY; +} + +/** + * System that manages the generation of textures from the renderer. + * @memberof PIXI + */ +export class GenerateTextureSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + name: 'textureGenerator', + }; + + renderer: IRenderer; + + private readonly _tempMatrix: Matrix; + + constructor(renderer: IRenderer) + { + this.renderer = renderer; + + this._tempMatrix = new Matrix(); + } + + /** + * A Useful function that returns a texture of the display object that can then be used to create sprites + * This can be quite useful if your displayObject is complicated and needs to be reused multiple times. + * @param displayObject - The displayObject the object will be generated from. + * @param {IGenerateTextureOptions} options - Generate texture options. + * @returns a shiny new texture of the display object passed in + */ + generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): RenderTexture + { + const { region: manualRegion, ...textureOptions } = options || {}; + + const region = manualRegion || (displayObject as IRenderableContainer).getLocalBounds(null, true); + + // minimum texture size is 1x1, 0x0 will throw an error + if (region.width === 0) region.width = 1; + if (region.height === 0) region.height = 1; + + const renderTexture = RenderTexture.create( + { + width: region.width, + height: region.height, + ...textureOptions, + }); + + this._tempMatrix.tx = -region.x; + this._tempMatrix.ty = -region.y; + + const transform = displayObject.transform; + + displayObject.transform = tempTransform; + + this.renderer.render(displayObject, { + renderTexture, + transform: this._tempMatrix, + skipUpdateTransform: !!displayObject.parent, + blit: true, + }); + + displayObject.transform = transform; + + return renderTexture; + } + + destroy(): void + { + // ka boom! + } +} + +extensions.add(GenerateTextureSystem); diff --git a/packages/core/src/renderTexture/RenderTexture.ts b/packages/core/src/renderTexture/RenderTexture.ts index ce0c2d618e0..c4f80167b60 100644 --- a/packages/core/src/renderTexture/RenderTexture.ts +++ b/packages/core/src/renderTexture/RenderTexture.ts @@ -4,8 +4,7 @@ import { Texture } from '../textures/Texture'; import type { Rectangle } from '@pixi/math'; import type { Framebuffer } from '../framebuffer/Framebuffer'; import type { IBaseTextureOptions } from '../textures/BaseTexture'; -import type { MSAA_QUALITY, SCALE_MODES } from '@pixi/constants'; -import { deprecation } from '@pixi/utils'; +import type { MSAA_QUALITY } from '@pixi/constants'; /** * A RenderTexture is a special texture that allows any PixiJS display object to be rendered to it. @@ -43,7 +42,6 @@ import { deprecation } from '@pixi/utils'; * * renderer.render(sprite, {renderTexture}); // Renders to center of RenderTexture * ``` - * * @memberof PIXI */ export class RenderTexture extends Texture @@ -54,17 +52,15 @@ export class RenderTexture extends Texture * Stores `sourceFrame` when this texture is inside current filter stack. * * You can read it inside filters. - * * @readonly */ - public filterFrame: Rectangle|null; + public filterFrame: Rectangle | null; /** * The key for pooled texture of FilterSystem. - * * @see PIXI.RenderTexturePool */ - public filterPoolKey: string|number|null; + public filterPoolKey: string | number | null; /** * @param baseRenderTexture - The base texture object that this texture uses. @@ -84,7 +80,6 @@ export class RenderTexture extends Texture /** * Shortcut to `this.baseTexture.framebuffer`, saves baseTexture cast. - * * @readonly */ get framebuffer(): Framebuffer @@ -94,7 +89,6 @@ export class RenderTexture extends Texture /** * Shortcut to `this.framebuffer.multisample`. - * * @default PIXI.MSAA_QUALITY.NONE */ get multisample(): MSAA_QUALITY @@ -109,7 +103,6 @@ export class RenderTexture extends Texture /** * Resizes the RenderTexture. - * * @param desiredWidth - The desired width to resize to. * @param desiredHeight - The desired height to resize to. * @param resizeBaseTexture - Should the baseTexture.width and height values be resized as well? @@ -136,7 +129,6 @@ export class RenderTexture extends Texture /** * Changes the resolution of baseTexture, but does not change framebuffer size. - * * @param resolution - The new resolution to apply to RenderTexture */ setResolution(resolution: number): void @@ -152,20 +144,8 @@ export class RenderTexture extends Texture this.resize(baseTexture.width, baseTexture.height, false); } - /** - * Use the object-based construction instead. - * - * @deprecated since 6.0.0 - * @param {number} [width] - * @param {number} [height] - * @param {PIXI.SCALE_MODES} [scaleMode=PIXI.settings.SCALE_MODE] - * @param {number} [resolution=PIXI.settings.FILTER_RESOLUTION] - */ - static create(width: number, height: number, scaleMode?: SCALE_MODES, resolution?: number): RenderTexture; - /** * A short hand way of creating a render texture. - * * @param options - Options * @param {number} [options.width=100] - The width of the render texture * @param {number} [options.height=100] - The height of the render texture @@ -174,28 +154,10 @@ export class RenderTexture extends Texture * @param {number} [options.resolution=PIXI.settings.RESOLUTION] - The resolution / device pixel ratio of the texture * being generated * @param {PIXI.MSAA_QUALITY} [options.multisample=PIXI.MSAA_QUALITY.NONE] - The number of samples of the frame buffer - * @return The new render texture + * @returns The new render texture */ - static create(options?: IBaseTextureOptions): RenderTexture; - static create(options?: IBaseTextureOptions | number, ...rest: any[]): RenderTexture + static create(options?: IBaseTextureOptions): RenderTexture { - // @deprecated fallback, old-style: create(width, height, scaleMode, resolution) - if (typeof options === 'number') - { - // #if _DEBUG - deprecation('6.0.0', 'Arguments (width, height, scaleMode, resolution) have been deprecated.'); - // #endif - - /* eslint-disable prefer-rest-params */ - options = { - width: options, - height: rest[0], - scaleMode: rest[1], - resolution: rest[2], - }; - /* eslint-enable prefer-rest-params */ - } - return new RenderTexture(new BaseRenderTexture(options)); } } diff --git a/packages/core/src/renderTexture/RenderTexturePool.ts b/packages/core/src/renderTexture/RenderTexturePool.ts index 08c45f24f73..e24a31771ea 100644 --- a/packages/core/src/renderTexture/RenderTexturePool.ts +++ b/packages/core/src/renderTexture/RenderTexturePool.ts @@ -13,7 +13,6 @@ import type { ISize } from '@pixi/math'; * * If you use custom RenderTexturePool for your filters, you can use methods * `getFilterTexture` and `returnFilterTexture` same as in - * * @memberof PIXI */ export class RenderTexturePool @@ -24,11 +23,10 @@ export class RenderTexturePool * Allow renderTextures of the same size as screen, not just pow2 * * Automatically sets to true after `setScreenSize` - * * @default false */ public enableFullScreen: boolean; - texturePool: {[x in string|number]: RenderTexture[]}; + texturePool: {[x in string | number]: RenderTexture[]}; private _pixelsWidth: number; private _pixelsHeight: number; @@ -48,7 +46,6 @@ export class RenderTexturePool /** * Creates texture with params that were specified in pool constructor. - * * @param realWidth - Width of texture in pixels. * @param realHeight - Height of texture in pixels. * @param multisample - Number of samples of the framebuffer. @@ -67,12 +64,11 @@ export class RenderTexturePool /** * Gets a Power-of-Two render texture or fullScreen texture - * * @param minWidth - The minimum width of the render texture. * @param minHeight - The minimum height of the render texture. * @param resolution - The resolution of the render texture. * @param multisample - Number of samples of the render texture. - * @return The new render texture. + * @returns The new render texture. */ getOptimalTexture(minWidth: number, minHeight: number, resolution = 1, multisample = MSAA_QUALITY.NONE): RenderTexture { @@ -119,12 +115,10 @@ export class RenderTexturePool * Gets extra texture of the same size as input renderTexture * * `getFilterTexture(input, 0.5)` or `getFilterTexture(0.5, input)` - * * @param input - renderTexture from which size and resolution will be copied * @param resolution - override resolution of the renderTexture * It overrides, it does not multiply * @param multisample - number of samples of the renderTexture - * @returns */ getFilterTexture(input: RenderTexture, resolution?: number, multisample?: MSAA_QUALITY): RenderTexture { @@ -138,7 +132,6 @@ export class RenderTexturePool /** * Place a render texture back into the pool. - * * @param renderTexture - The renderTexture to free */ returnTexture(renderTexture: RenderTexture): void @@ -151,7 +144,6 @@ export class RenderTexturePool /** * Alias for returnTexture, to be compliant with FilterSystem interface. - * * @param renderTexture - The renderTexture to free */ returnFilterTexture(renderTexture: RenderTexture): void @@ -161,7 +153,6 @@ export class RenderTexturePool /** * Clears the pool. - * * @param destroyTextures - Destroy all stored textures. */ clear(destroyTextures?: boolean): void @@ -191,7 +182,6 @@ export class RenderTexturePool * sets new screen size, sets `enableFullScreen` to true * * Size is measured in pixels, `renderer.view` can be passed here, not `renderer.screen` - * * @param size - Initial size of screen. */ setScreenSize(size: ISize): void @@ -230,7 +220,6 @@ export class RenderTexturePool /** * Key that is used to store fullscreen renderTextures in a pool - * * @constant */ static SCREEN_KEY = -1; diff --git a/packages/core/src/renderTexture/RenderTextureSystem.ts b/packages/core/src/renderTexture/RenderTextureSystem.ts index 6c63f4d693d..af5fedf4cd8 100644 --- a/packages/core/src/renderTexture/RenderTextureSystem.ts +++ b/packages/core/src/renderTexture/RenderTextureSystem.ts @@ -1,12 +1,14 @@ import { Rectangle } from '@pixi/math'; -import { BUFFER_BITS } from '@pixi/constants'; +import type { BUFFER_BITS } from '@pixi/constants'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; import type { RenderTexture } from './RenderTexture'; import type { BaseRenderTexture } from './BaseRenderTexture'; import type { MaskData } from '../mask/MaskData'; import type { ISize } from '@pixi/math'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; // Temporary rectangle for assigned sourceFrame or destinationFrame const tempRect = new Rectangle(); @@ -30,26 +32,26 @@ const tempRect2 = new Rectangle(); * | sourceFrame | The rectangle inside of which display-objects are being rendered | **World Space**: The origin on the top-left | * | destinationFrame | The rectangle in the render-target (canvas or texture) into which contents should be rendered | If rendering to the canvas, this is in screen space and the origin is on the top-left. If rendering to a render-texture, this is in its base-texture's space with the origin on the bottom-left. | * | viewportFrame | The framebuffer viewport corresponding to the destination-frame | **Window Coordinates**: The origin is always on the bottom-left. | - * * @memberof PIXI */ export class RenderTextureSystem implements ISystem { -/* eslint-enable max-len */ + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'renderTexture', + }; - /** The clear background color as RGBA. */ - public clearColor: number[]; + /* eslint-enable max-len */ /** * List of masks for the {@link PIXI.StencilSystem}. - * * @readonly */ public defaultMaskStack: Array; /** * Render texture currently bound. {@code null} if rendering to the canvas. - * * @readonly */ public current: RenderTexture | null; @@ -84,7 +86,6 @@ export class RenderTextureSystem implements ISystem { this.renderer = renderer; - this.clearColor = renderer._backgroundColorRgba; this.defaultMaskStack = []; this.current = null; this.sourceFrame = new Rectangle(); @@ -94,7 +95,6 @@ export class RenderTextureSystem implements ISystem /** * Bind the current render texture. - * * @param renderTexture - RenderTexture to bind, by default its `null` - the screen. * @param sourceFrame - Part of world that is mapped to the renderTexture. * @param destinationFrame - Part of renderTexture, by default it has the same size as sourceFrame. @@ -141,8 +141,8 @@ export class RenderTextureSystem implements ISystem if (!sourceFrame) { - tempRect.width = renderer.screen.width; - tempRect.height = renderer.screen.height; + tempRect.width = renderer._view.screen.width; + tempRect.height = renderer._view.screen.height; sourceFrame = tempRect; } @@ -188,7 +188,6 @@ export class RenderTextureSystem implements ISystem /** * Erases the render texture and fills the drawing area with a colour. - * * @param clearColor - The color as rgba, default to use the renderer backgroundColor * @param [mask=BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH] - Bitwise OR of masks * that indicate the buffers to be cleared, by default COLOR and DEPTH buffers. @@ -201,11 +200,11 @@ export class RenderTextureSystem implements ISystem } else { - clearColor = clearColor || this.clearColor; + clearColor = clearColor || this.renderer.background.colorRgba; } const destinationFrame = this.destinationFrame; - const baseFrame: ISize = this.current ? this.current.baseTexture : this.renderer.screen; + const baseFrame: ISize = this.current ? this.current.baseTexture : this.renderer._view.screen; const clearMask = destinationFrame.width !== baseFrame.width || destinationFrame.height !== baseFrame.height; if (clearMask) @@ -248,3 +247,5 @@ export class RenderTextureSystem implements ISystem this.renderer = null; } } + +extensions.add(RenderTextureSystem); diff --git a/packages/core/src/settings.ts b/packages/core/src/settings.ts index 844699a48bc..83f21f97756 100644 --- a/packages/core/src/settings.ts +++ b/packages/core/src/settings.ts @@ -1,6 +1,5 @@ import { settings } from '@pixi/settings'; import { ENV } from '@pixi/constants'; -import { isMobile } from '@pixi/utils'; /** * The maximum support for using WebGL. If a device does not @@ -8,17 +7,13 @@ import { isMobile } from '@pixi/utils'; * attempt to fallback support to WebGL 1. If you want to * explicitly remove feature support to target a more stable * baseline, prefer a lower environment. - * - * Due to {@link https://bugs.chromium.org/p/chromium/issues/detail?id=934823|bug in chromium} - * we disable webgl2 by default for all non-apple mobile devices. - * * @static * @name PREFER_ENV * @memberof PIXI.settings * @type {number} * @default PIXI.ENV.WEBGL2 */ -settings.PREFER_ENV = isMobile.any ? ENV.WEBGL : ENV.WEBGL2; +settings.PREFER_ENV = ENV.WEBGL2; /** * If set to `true`, *only* Textures and BaseTexture objects stored @@ -29,7 +24,6 @@ settings.PREFER_ENV = isMobile.any ? ENV.WEBGL : ENV.WEBGL2; * Otherwise, these `from` calls throw an exception. Using this property * can be useful if you want to enforce preloading all assets with * {@link PIXI.Loader Loader}. - * * @static * @name STRICT_TEXTURE_CACHE * @memberof PIXI.settings diff --git a/packages/core/src/shader/GLProgram.ts b/packages/core/src/shader/GLProgram.ts index 4f2496e9d19..7d65e803ff7 100644 --- a/packages/core/src/shader/GLProgram.ts +++ b/packages/core/src/shader/GLProgram.ts @@ -11,7 +11,6 @@ export class IGLUniformData /** * Helper class to create a WebGL Program - * * @memberof PIXI */ export class GLProgram @@ -46,7 +45,6 @@ export class GLProgram /** * Makes a new Pixi program. - * * @param program - webgl program * @param uniformData - uniforms */ diff --git a/packages/core/src/shader/Program.ts b/packages/core/src/shader/Program.ts index bd87c241da7..4e36dd8c274 100644 --- a/packages/core/src/shader/Program.ts +++ b/packages/core/src/shader/Program.ts @@ -32,7 +32,6 @@ export interface IUniformData /** * Helper class to create a shader program. - * * @memberof PIXI */ export class Program @@ -99,7 +98,6 @@ export class Program /** * The default vertex shader source. - * * @constant */ static get defaultVertexSrc(): string @@ -109,7 +107,6 @@ export class Program /** * The default fragment shader source. - * * @constant */ static get defaultFragmentSrc(): string @@ -121,7 +118,6 @@ export class Program * A short hand function to create a program based of a vertex and fragment shader. * * This method will also check to see if there is a cached program. - * * @param vertexSrc - The source of the vertex shader. * @param fragmentSrc - The source of the fragment shader. * @param name - Name for shader diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index e693e52c040..67b500a3fdf 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -5,7 +5,6 @@ import type { Dict } from '@pixi/utils'; /** * A helper class for shaders. - * * @memberof PIXI */ export class Shader @@ -80,7 +79,6 @@ export class Shader /** * Shader uniform values, shortcut for `uniformGroup.uniforms`. - * * @readonly */ get uniforms(): Dict @@ -90,7 +88,6 @@ export class Shader /** * A short hand function to create a shader based of a vertex and fragment shader. - * * @param vertexSrc - The source of the vertex shader. * @param fragmentSrc - The source of the fragment shader. * @param uniforms - Custom uniforms to use to augment the built-in ones. diff --git a/packages/core/src/shader/ShaderSystem.ts b/packages/core/src/shader/ShaderSystem.ts index 1b9bdc92be4..49abe944421 100644 --- a/packages/core/src/shader/ShaderSystem.ts +++ b/packages/core/src/shader/ShaderSystem.ts @@ -1,9 +1,8 @@ -import { GLProgram } from './GLProgram'; +import type { GLProgram } from './GLProgram'; import { generateUniformsSync, unsafeEvalSupported } from './utils'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; -import type { IRenderingContext } from '../IRenderingContext'; import type { Shader } from './Shader'; import type { Program } from './Program'; import type { UniformGroup } from './UniformGroup'; @@ -12,6 +11,9 @@ import type { UniformsSyncCallback } from './utils'; import { generateUniformBufferSync } from './utils/generateUniformBufferSync'; import { generateProgram } from './utils/generateProgram'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; let UID = 0; // default sync data so we don't create a new one each time! @@ -19,14 +21,18 @@ const defaultSyncData = { textureCount: 0, uboCount: 0 }; /** * System plugin to the renderer to manage shaders. - * * @memberof PIXI */ export class ShaderSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'shader', + }; + /** * The current WebGL rendering context. - * * @member {WebGLRenderingContext} */ protected gl: IRenderingContext; @@ -63,10 +69,9 @@ export class ShaderSystem implements ISystem /** * Overrideable function by `@pixi/unsafe-eval` to silence * throwing an error if platform doesn't support unsafe-evals. - * * @private */ - systemCheck(): void + private systemCheck(): void { if (!unsafeEvalSupported()) { @@ -83,7 +88,6 @@ export class ShaderSystem implements ISystem /** * Changes the current shader to the one given in parameter. - * * @param shader - the new shader * @param dontSync - false if the shader should automatically sync its uniforms. * @returns the glProgram that belongs to the shader. @@ -117,7 +121,6 @@ export class ShaderSystem implements ISystem /** * Uploads the uniforms values to the currently bound shader. - * * @param uniforms - the uniforms values that be applied to the current shader */ setUniforms(uniforms: Dict): void @@ -131,7 +134,6 @@ export class ShaderSystem implements ISystem /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /** * Syncs uniforms on the group - * * @param group - the uniform group to sync * @param syncData - this is data that is passed to the sync function and any nested sync functions */ @@ -149,6 +151,9 @@ export class ShaderSystem implements ISystem /** * Overrideable by the @pixi/unsafe-eval package to use static syncUniforms instead. + * @param group + * @param glProgram + * @param syncData */ syncUniforms(group: UniformGroup, glProgram: GLProgram, syncData: any): void { @@ -173,7 +178,6 @@ export class ShaderSystem implements ISystem /** * Syncs uniform buffers - * * @param group - the uniform buffer group to sync * @param name - the name of the uniform buffer */ @@ -206,7 +210,6 @@ export class ShaderSystem implements ISystem * Will create a function that uploads a uniform buffer using the STD140 standard. * The upload function will then be cached for future calls * If a group is manually managed, then a simple upload function is generated - * * @param group - the uniform buffer group to sync * @param glProgram - the gl program to attach the uniform bindings to * @param name - the name of the uniform buffer (must exist on the shader) @@ -249,9 +252,10 @@ export class ShaderSystem implements ISystem /** * Takes a uniform group and data and generates a unique signature for them. - * * @param group - The uniform group to get signature of + * @param group.uniforms * @param uniformData - Uniform information generated by the shader + * @param preFix * @returns Unique signature of the uniform group */ private getSignature(group: {uniforms: Dict}, uniformData: Dict, preFix: string): string @@ -277,8 +281,7 @@ export class ShaderSystem implements ISystem * Returns the underlying GLShade rof the currently bound shader. * * This can be handy for when you to have a little more control over the setting of your uniforms. - * - * @return The glProgram for the currently bound Shader for this context + * @returns The glProgram for the currently bound Shader for this context */ getGlProgram(): GLProgram { @@ -292,9 +295,8 @@ export class ShaderSystem implements ISystem /** * Generates a glProgram version of the Shader provided. - * * @param shader - The shader that the glProgram will be based on. - * @return A shiny new glProgram! + * @returns A shiny new glProgram! */ generateProgram(shader: Shader): GLProgram { @@ -323,3 +325,5 @@ export class ShaderSystem implements ISystem this.destroyed = true; } } + +extensions.add(ShaderSystem); diff --git a/packages/core/src/shader/UniformGroup.ts b/packages/core/src/shader/UniformGroup.ts index 7b5aadac7de..3f212224ecd 100644 --- a/packages/core/src/shader/UniformGroup.ts +++ b/packages/core/src/shader/UniformGroup.ts @@ -45,28 +45,24 @@ let UID = 0; * }) * * ``` - * * @memberof PIXI */ export class UniformGroup> { /** * Uniform values - * * @member {object} */ public readonly uniforms: LAYOUT; /** * Its a group and not a single uniforms. - * * @default true */ public readonly group: boolean; /** * unique id - * * @protected */ public id: number; @@ -74,7 +70,6 @@ export class UniformGroup> /** * Dirty version - * * @protected */ dirtyId: number; @@ -153,7 +148,6 @@ export class UniformGroup> /** * A short hand function for creating a static UBO UniformGroup. - * * @param uniforms - the ubo item * @param _static - should this be updated each time it is used? defaults to true here! */ diff --git a/packages/core/src/shader/utils/checkMaxIfStatementsInShader.ts b/packages/core/src/shader/utils/checkMaxIfStatementsInShader.ts index 208cf90adb9..b67ada0140b 100644 --- a/packages/core/src/shader/utils/checkMaxIfStatementsInShader.ts +++ b/packages/core/src/shader/utils/checkMaxIfStatementsInShader.ts @@ -1,4 +1,4 @@ -import type { IRenderingContext } from '../../IRenderingContext'; +import type { IRenderingContext } from '../../IRenderer'; const fragTemplate = [ 'precision mediump float;', diff --git a/packages/core/src/shader/utils/compileShader.ts b/packages/core/src/shader/utils/compileShader.ts index d4fdf18e10b..7821e1ec265 100644 --- a/packages/core/src/shader/utils/compileShader.ts +++ b/packages/core/src/shader/utils/compileShader.ts @@ -1,9 +1,9 @@ /** * @private * @param {WebGLRenderingContext} gl - The current WebGL context {WebGLProgram} - * @param {Number} type - the type, can be either VERTEX_SHADER or FRAGMENT_SHADER + * @param {number} type - the type, can be either VERTEX_SHADER or FRAGMENT_SHADER * @param {string} src - The vertex shader source as an array of strings. - * @return {WebGLShader} the shader + * @returns {WebGLShader} the shader */ export function compileShader(gl: WebGLRenderingContextBase, type: number, src: string): WebGLShader { diff --git a/packages/core/src/shader/utils/defaultValue.ts b/packages/core/src/shader/utils/defaultValue.ts index 748e8c0afd9..74824226e2e 100644 --- a/packages/core/src/shader/utils/defaultValue.ts +++ b/packages/core/src/shader/utils/defaultValue.ts @@ -17,7 +17,10 @@ function booleanArray(size: number): Array * @param {number} size * @private */ -export function defaultValue(type: string, size: number): number|Float32Array|Int32Array|Uint32Array|boolean|boolean[] +export function defaultValue( + type: string, + size: number +): number | Float32Array | Int32Array | Uint32Array | boolean | boolean[] { switch (type) { diff --git a/packages/core/src/shader/utils/generateProgram.ts b/packages/core/src/shader/utils/generateProgram.ts index 5653e574bbf..77bdae52a46 100644 --- a/packages/core/src/shader/utils/generateProgram.ts +++ b/packages/core/src/shader/utils/generateProgram.ts @@ -1,5 +1,4 @@ -import { Program } from '../Program'; -import type { IRenderingContext } from '../../IRenderingContext'; +import type { Program } from '../Program'; import type { IGLUniformData } from '../GLProgram'; import { GLProgram } from '../GLProgram'; import { compileShader } from './compileShader'; @@ -7,10 +6,10 @@ import { defaultValue } from './defaultValue'; import { getAttributeData } from './getAttributeData'; import { getUniformData } from './getUniformData'; import { logProgramError } from './logProgramError'; +import type { IRenderingContext } from '../../IRenderer'; /** * generates a WebGL Program object from a high level Pixi Program. - * * @param gl - a rendering context on which to generate the program * @param program - the high level Pixi Program. */ diff --git a/packages/core/src/shader/utils/generateUniformBufferSync.ts b/packages/core/src/shader/utils/generateUniformBufferSync.ts index 43116e978ec..e8ac65261d3 100644 --- a/packages/core/src/shader/utils/generateUniformBufferSync.ts +++ b/packages/core/src/shader/utils/generateUniformBufferSync.ts @@ -1,7 +1,7 @@ import type { Dict } from '@pixi/utils'; import { mapSize } from '../utils'; -import { IUniformData } from '../Program'; -import { UniformGroup } from '../UniformGroup'; +import type { IUniformData } from '../Program'; +import type { UniformGroup } from '../UniformGroup'; import { uniformParsers } from './uniformParsers'; import type { Renderer } from '../../Renderer'; import type { Buffer } from '../../geometry/Buffer'; @@ -92,7 +92,8 @@ const GLSL_TO_STD40_SIZE: Dict = { mat4: 16 * 4, }; -interface UBOElement { +interface UBOElement +{ data: IUniformData offset: number, dataLen: number, @@ -100,11 +101,9 @@ interface UBOElement { } /** - * @ignore - * * logic originally from here: https://github.com/sketchpunk/FunWithWebGL2/blob/master/lesson_022/Shaders.js * rewrote it, but this was a great starting point to get a solid understanding of whats going on :) - * + * @ignore * @param uniformData */ export function createUBOElements(uniformData: IUniformData[]): {uboElements: UBOElement[], size: number} diff --git a/packages/core/src/shader/utils/generateUniformsSync.ts b/packages/core/src/shader/utils/generateUniformsSync.ts index 199c7657881..f67cac71de0 100644 --- a/packages/core/src/shader/utils/generateUniformsSync.ts +++ b/packages/core/src/shader/utils/generateUniformsSync.ts @@ -158,9 +158,27 @@ const GLSL_TO_SINGLE_SETTERS_CACHED: Dict = { mat3: 'gl.uniformMatrix3fv(location, false, v)', mat4: 'gl.uniformMatrix4fv(location, false, v)', - sampler2D: 'gl.uniform1i(location, v)', - samplerCube: 'gl.uniform1i(location, v)', - sampler2DArray: 'gl.uniform1i(location, v)', + sampler2D: ` + if (cv !== v) + { + cu.value = v; + + gl.uniform1i(location, v); + }`, + samplerCube: ` + if (cv !== v) + { + cu.value = v; + + gl.uniform1i(location, v); + }`, + sampler2DArray: ` + if (cv !== v) + { + cu.value = v; + + gl.uniform1i(location, v); + }`, }; const GLSL_TO_ARRAY_SETTERS: Dict = { diff --git a/packages/core/src/shader/utils/getAttributeData.ts b/packages/core/src/shader/utils/getAttributeData.ts index de046eb6cc8..9bfa766961f 100644 --- a/packages/core/src/shader/utils/getAttributeData.ts +++ b/packages/core/src/shader/utils/getAttributeData.ts @@ -1,14 +1,12 @@ -import { IAttributeData } from '../Program'; +import type { IAttributeData } from '../Program'; import { mapSize } from './mapSize'; import { mapType } from './mapType'; /** * returns the attribute data from the program * @private - * * @param {WebGLProgram} [program] - the WebGL program * @param {WebGLRenderingContext} [gl] - the WebGL context - * * @returns {object} the attribute data for this program */ export function getAttributeData(program: WebGLProgram, gl: WebGLRenderingContextBase): {[key: string]: IAttributeData} @@ -21,7 +19,7 @@ export function getAttributeData(program: WebGLProgram, gl: WebGLRenderingContex { const attribData = gl.getActiveAttrib(program, i); - if (attribData.name.indexOf('gl_') === 0) + if (attribData.name.startsWith('gl_')) { continue; } diff --git a/packages/core/src/shader/utils/getTestContext.ts b/packages/core/src/shader/utils/getTestContext.ts index c39f6ae0ab9..229f805a717 100644 --- a/packages/core/src/shader/utils/getTestContext.ts +++ b/packages/core/src/shader/utils/getTestContext.ts @@ -6,16 +6,15 @@ let context: WebGLRenderingContext | WebGL2RenderingContext = unknownContext as /** * returns a little WebGL context to use for program inspection. - * * @static * @private * @returns {WebGLRenderingContext} a gl context to test with */ export function getTestContext(): WebGLRenderingContext | WebGL2RenderingContext { - if (context === unknownContext || (context && context.isContextLost())) + if (context === unknownContext || context?.isContextLost()) { - const canvas = document.createElement('canvas'); + const canvas = settings.ADAPTER.createCanvas(); let gl: WebGLRenderingContext | WebGL2RenderingContext; @@ -26,8 +25,8 @@ export function getTestContext(): WebGLRenderingContext | WebGL2RenderingContext if (!gl) { - gl = canvas.getContext('webgl', {}) - || (canvas.getContext('experimental-webgl', {}) as WebGLRenderingContext); + gl = (canvas.getContext('webgl', {}) + || (canvas.getContext('experimental-webgl', {}) as WebGLRenderingContext)); if (!gl) { diff --git a/packages/core/src/shader/utils/getUniformData.ts b/packages/core/src/shader/utils/getUniformData.ts index 1d254c90002..75f3410a6ca 100644 --- a/packages/core/src/shader/utils/getUniformData.ts +++ b/packages/core/src/shader/utils/getUniformData.ts @@ -1,14 +1,12 @@ -import { IUniformData } from '../Program'; +import type { IUniformData } from '../Program'; import { defaultValue } from './defaultValue'; import { mapType } from './mapType'; /** * returns the uniform data from the program * @private - * * @param program - the webgl program * @param gl - the WebGL context - * * @returns {object} the uniform data for this program */ export function getUniformData(program: WebGLProgram, gl: WebGLRenderingContextBase): {[key: string]: IUniformData} diff --git a/packages/core/src/shader/utils/logProgramError.ts b/packages/core/src/shader/utils/logProgramError.ts index 8ae819bfd49..5e649446bff 100644 --- a/packages/core/src/shader/utils/logProgramError.ts +++ b/packages/core/src/shader/utils/logProgramError.ts @@ -1,7 +1,6 @@ /** * will log a shader error highlighting the lines with the error * also will add numbers along the side. - * * @param gl - the WebGLContext * @param shader - the shader to log errors for */ @@ -54,7 +53,6 @@ function logPrettyShaderError(gl: WebGLRenderingContext, shader: WebGLShader): v /** * * logs out any program errors - * * @param gl - The current WebGL context * @param program - the WebGL program to display errors for * @param vertexShader - the fragment WebGL shader program diff --git a/packages/core/src/shader/utils/mapSize.ts b/packages/core/src/shader/utils/mapSize.ts index 9d32e96263e..1b37e3d829a 100644 --- a/packages/core/src/shader/utils/mapSize.ts +++ b/packages/core/src/shader/utils/mapSize.ts @@ -32,8 +32,7 @@ const GLSL_TO_SIZE: Dict = { * @private * @method mapSize * @memberof PIXI.glCore.shader - * @param {String} type - * @return {Number} + * @param {string} type */ export function mapSize(type: string): number { diff --git a/packages/core/src/shader/utils/setPrecision.ts b/packages/core/src/shader/utils/setPrecision.ts index 292169a31fe..78aa37920d1 100644 --- a/packages/core/src/shader/utils/setPrecision.ts +++ b/packages/core/src/shader/utils/setPrecision.ts @@ -3,13 +3,11 @@ import { PRECISION } from '@pixi/constants'; /** * Sets the float precision on the shader, ensuring the device supports the request precision. * If the precision is already present, it just ensures that the device is able to handle it. - * * @private * @param {string} src - The shader source * @param {PIXI.PRECISION} requestedPrecision - The request float precision of the shader. * @param {PIXI.PRECISION} maxSupportedPrecision - The maximum precision the shader supports. - * - * @return {string} modified shader source + * @returns {string} modified shader source */ export function setPrecision(src: string, requestedPrecision: PRECISION, maxSupportedPrecision: PRECISION): string { diff --git a/packages/core/src/shader/utils/uniformParsers.ts b/packages/core/src/shader/utils/uniformParsers.ts index ff6fcb5b3b3..7ce5db8a1fc 100644 --- a/packages/core/src/shader/utils/uniformParsers.ts +++ b/packages/core/src/shader/utils/uniformParsers.ts @@ -39,9 +39,9 @@ export const uniformParsers: IUniformParser[] = [ }, // handling samplers { - test: (data: any): boolean => - // eslint-disable-next-line max-len - (data.type === 'sampler2D' || data.type === 'samplerCube' || data.type === 'sampler2DArray') && data.size === 1 && !data.isArray, + test: (data: any, uniform: any): boolean => + // eslint-disable-next-line max-len,no-eq-null,eqeqeq + (data.type === 'sampler2D' || data.type === 'samplerCube' || data.type === 'sampler2DArray') && data.size === 1 && !data.isArray && (uniform == null || uniform.castToBaseTexture !== undefined), code: (name: string): string => `t = syncData.textureCount++; renderer.texture.bind(uv["${name}"], t); diff --git a/packages/core/src/shader/utils/unsafeEvalSupported.ts b/packages/core/src/shader/utils/unsafeEvalSupported.ts index 408fc318526..c5799778556 100644 --- a/packages/core/src/shader/utils/unsafeEvalSupported.ts +++ b/packages/core/src/shader/utils/unsafeEvalSupported.ts @@ -4,9 +4,8 @@ let unsafeEval: boolean; /** * Not all platforms allow to generate function code (e.g., `new Function`). * this provides the platform-level detection. - * * @private - * @returns {boolean} + * @returns {boolean} `true` if `new Function` is supported. */ export function unsafeEvalSupported(): boolean { diff --git a/packages/core/src/startup/StartupSystem.ts b/packages/core/src/startup/StartupSystem.ts new file mode 100644 index 00000000000..6579528a234 --- /dev/null +++ b/packages/core/src/startup/StartupSystem.ts @@ -0,0 +1,62 @@ +import { sayHello } from '@pixi/utils'; +import type { BackgroundOptions } from '../background/BackgroundSystem'; +import type { ViewOptions } from '../view/ViewSystem'; +import type { IRendererPlugins } from '../plugin/PluginSystem'; +import type { IRenderer } from '../IRenderer'; +import type { ISystem } from '../system/ISystem'; +import type { ContextOptions } from '../systems'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; + +// TODO this can be infered by good use of generics in the future.. +export interface StartupOptions extends Record +{ + _plugin: IRendererPlugins, + background: BackgroundOptions, + _view: ViewOptions, + context?: ContextOptions +} + +/** + * A simple system responsible for initiating the renderer. + * @memberof PIXI + */export class StartupSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + name: 'startup', + }; + + readonly renderer: IRenderer; + + constructor(renderer: IRenderer) + { + this.renderer = renderer; + } + + /** + * It all starts here! This initiates every system, passing in the options for any system by name. + * @param options - the config for the renderer and all its systems + */ + run(options: StartupOptions): void + { + const renderer = this.renderer; + + renderer.emitWithCustomOptions(renderer.runners.init, options); + + sayHello(renderer.rendererLogId); + + renderer.resize(this.renderer.screen.width, this.renderer.screen.height); + } + + destroy(): void + { + // ka pow! + } +} + +extensions.add(StartupSystem); diff --git a/packages/core/src/state/State.ts b/packages/core/src/state/State.ts index 83a3f2cebef..908deccafd2 100644 --- a/packages/core/src/state/State.ts +++ b/packages/core/src/state/State.ts @@ -14,7 +14,6 @@ const DEPTH_MASK = 5; * * Each mesh rendered may require WebGL to be in a different state. * For example you may want different blend mode or to enable polygon offsets - * * @memberof PIXI */ export class State @@ -37,7 +36,6 @@ export class State /** * Activates blending of the computed fragment color values. - * * @default true */ get blend(): boolean @@ -55,7 +53,6 @@ export class State /** * Activates adding an offset to depth values of polygon's fragments - * * @default false */ get offsets(): boolean @@ -73,7 +70,6 @@ export class State /** * Activates culling of polygons. - * * @default false */ get culling(): boolean @@ -91,7 +87,6 @@ export class State /** * Activates depth comparisons and updates to the depth buffer. - * * @default false */ get depthTest(): boolean @@ -109,7 +104,6 @@ export class State /** * Enables or disables writing to the depth buffer. - * * @default true */ get depthMask(): boolean @@ -127,7 +121,6 @@ export class State /** * Specifies whether or not front or back-facing polygons can be culled. - * * @default false */ get clockwiseFrontFace(): boolean @@ -146,7 +139,6 @@ export class State /** * The blend mode to be applied when this state is set. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode. * Setting this mode to anything other than NO_BLEND will automatically switch blending on. - * * @default PIXI.BLEND_MODES.NORMAL */ get blendMode(): BLEND_MODES @@ -162,7 +154,6 @@ export class State /** * The polygon offset. Setting this property to anything other than 0 will automatically enable polygon offset fill. - * * @default 0 */ get polygonOffset(): number diff --git a/packages/core/src/state/StateSystem.ts b/packages/core/src/state/StateSystem.ts index 7e3b7ee257c..6539f51c8a3 100644 --- a/packages/core/src/state/StateSystem.ts +++ b/packages/core/src/state/StateSystem.ts @@ -2,8 +2,10 @@ import { mapWebGLBlendModesToPixi } from './utils/mapWebGLBlendModesToPixi'; import { State } from './State'; import { BLEND_MODES } from '@pixi/constants'; -import type { ISystem } from '../ISystem'; -import type { IRenderingContext } from '../IRenderingContext'; +import type { ISystem } from '../system/ISystem'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; const BLEND = 0; const OFFSET = 1; @@ -14,11 +16,16 @@ const DEPTH_MASK = 5; /** * System plugin to the renderer to manage WebGL state machines. - * * @memberof PIXI */ export class StateSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'state', + }; + /** * State ID * @readonly @@ -52,13 +59,13 @@ export class StateSystem implements ISystem /** * Collection of calls - * @member {function[]} + * @member {Function[]} */ protected readonly map: Array<(value: boolean) => void>; /** * Collection of check calls - * @member {function[]} + * @member {Function[]} */ protected readonly checks: Array<(system: this, state: State) => void>; @@ -106,7 +113,6 @@ export class StateSystem implements ISystem /** * Sets the current state - * * @param {*} state - The state to set. */ set(state: State): void @@ -146,7 +152,6 @@ export class StateSystem implements ISystem /** * Sets the state, when previous state is unknown. - * * @param {*} state - The state to set */ forceState(state: State): void @@ -166,7 +171,6 @@ export class StateSystem implements ISystem /** * Sets whether to enable or disable blending. - * * @param value - Turn on or off WebGl blending. */ setBlend(value: boolean): void @@ -178,7 +182,6 @@ export class StateSystem implements ISystem /** * Sets whether to enable or disable polygon offset fill. - * * @param value - Turn on or off webgl polygon offset testing. */ setOffset(value: boolean): void @@ -190,7 +193,6 @@ export class StateSystem implements ISystem /** * Sets whether to enable or disable depth test. - * * @param value - Turn on or off webgl depth testing. */ setDepthTest(value: boolean): void @@ -200,7 +202,6 @@ export class StateSystem implements ISystem /** * Sets whether to enable or disable depth mask. - * * @param value - Turn on or off webgl depth mask. */ setDepthMask(value: boolean): void @@ -210,7 +211,6 @@ export class StateSystem implements ISystem /** * Sets whether to enable or disable cull face. - * * @param {boolean} value - Turn on or off webgl cull face. */ setCullFace(value: boolean): void @@ -220,7 +220,6 @@ export class StateSystem implements ISystem /** * Sets the gl front face. - * * @param {boolean} value - true is clockwise and false is counter-clockwise */ setFrontFace(value: boolean): void @@ -230,7 +229,6 @@ export class StateSystem implements ISystem /** * Sets the blend mode. - * * @param {number} value - The blend mode to set to. */ setBlendMode(value: number): void @@ -267,7 +265,6 @@ export class StateSystem implements ISystem /** * Sets the polygon offset. - * * @param {number} value - the polygon offset * @param {number} scale - the polygon offset scale */ @@ -295,7 +292,6 @@ export class StateSystem implements ISystem * For example, if blend is enabled then we should check the blend modes each time the state is changed * or if polygon fill is activated then we need to check if the polygon offset changes. * The idea is that we only check what we have too. - * * @param func - the checking function to add or remove * @param value - should the check function be added or removed. */ @@ -315,8 +311,7 @@ export class StateSystem implements ISystem /** * A private little wrapper function that we call to check the blend mode. - * - * @param System - the System to perform the state check on + * @param system - the System to perform the state check on * @param state - the state that the blendMode will pulled from */ private static checkBlendMode(system: StateSystem, state: State): void @@ -326,8 +321,7 @@ export class StateSystem implements ISystem /** * A private little wrapper function that we call to check the polygon offset. - * - * @param System - the System to perform the state check on + * @param system - the System to perform the state check on * @param state - the state that the blendMode will pulled from */ private static checkPolygonOffset(system: StateSystem, state: State): void @@ -343,3 +337,5 @@ export class StateSystem implements ISystem this.gl = null; } } + +extensions.add(StateSystem); diff --git a/packages/core/src/state/utils/mapWebGLBlendModesToPixi.ts b/packages/core/src/state/utils/mapWebGLBlendModesToPixi.ts index 6ff02679ec5..17daa5d2abb 100644 --- a/packages/core/src/state/utils/mapWebGLBlendModesToPixi.ts +++ b/packages/core/src/state/utils/mapWebGLBlendModesToPixi.ts @@ -2,13 +2,12 @@ import { BLEND_MODES } from '@pixi/constants'; /** * Maps gl blend combinations to WebGL. - * * @memberof PIXI * @function mapWebGLBlendModesToPixi * @private * @param {WebGLRenderingContext} gl - The rendering context. * @param {number[][]} [array=[]] - The array to output into. - * @return {number[][]} Mapped modes. + * @returns {number[][]} Mapped modes. */ export function mapWebGLBlendModesToPixi(gl: WebGLRenderingContextBase, array: number[][] = []): number[][] { diff --git a/packages/core/src/system/ISystem.ts b/packages/core/src/system/ISystem.ts new file mode 100644 index 00000000000..3a1540cec02 --- /dev/null +++ b/packages/core/src/system/ISystem.ts @@ -0,0 +1,21 @@ +import type { Renderer } from '../Renderer'; + +/** + * Interface for systems used by the {@link PIXI.Renderer}. + * @memberof PIXI + */ +export interface ISystem +{ + init?(options?: INIT_OPTIONS): void; + /** Generic destroy methods to be overridden by the subclass */ + destroy?(options?: DESTROY_OPTIONS): void; +} + +/** + * Types for system and pipe classes. + * @ignore + */ +export interface ISystemConstructor +{ + new (renderer: R): ISystem; +} diff --git a/packages/core/src/system/SystemManager.ts b/packages/core/src/system/SystemManager.ts new file mode 100644 index 00000000000..1bb6c4e75f6 --- /dev/null +++ b/packages/core/src/system/SystemManager.ts @@ -0,0 +1,154 @@ +import { Runner } from '@pixi/runner'; +import { EventEmitter } from '@pixi/utils'; +import type { IRenderer } from '../IRenderer'; +import type { ISystem, ISystemConstructor } from './ISystem'; +interface ISystemConfig +{ + runners: string[], + systems: Record> + priority: string[]; +} + +/** + * The SystemManager is a class that provides functions for managing a set of systems + * This is a base class, that is generic (no render code or knowledge at all) + * @memberof PIXI + */ +export class SystemManager extends EventEmitter +{ + /** a collection of runners defined by the user */ + readonly runners: {[key: string]: Runner} = {}; + + private _systemsHash: Record = {}; + + /** + * Set up a system with a collection of SystemClasses and runners. + * Systems are attached dynamically to this class when added. + * @param config - the config for the system manager + */ + setup(config: ISystemConfig): void + { + this.addRunners(...config.runners); + + // Remove keys that aren't available + const priority = (config.priority ?? []).filter((key) => config.systems[key]); + + // Order the systems by priority + const orderByPriority = [ + ...priority, + ...Object.keys(config.systems) + .filter((key) => !priority.includes(key)) + ]; + + for (const i of orderByPriority) + { + this.addSystem(config.systems[i], i); + } + } + + /** + * Create a bunch of runners based of a collection of ids + * @param runnerIds - the runner ids to add + */ + addRunners(...runnerIds: string[]): void + { + runnerIds.forEach((runnerId) => + { + this.runners[runnerId] = new Runner(runnerId); + }); + } + + /** + * Add a new system to the renderer. + * @param ClassRef - Class reference + * @param name - Property name for system, if not specified + * will use a static `name` property on the class itself. This + * name will be assigned as s property on the Renderer so make + * sure it doesn't collide with properties on Renderer. + * @returns Return instance of renderer + */ + addSystem(ClassRef: ISystemConstructor, name: string): this + { + const system = new ClassRef(this as any as R); + + if ((this as any)[name]) + { + throw new Error(`Whoops! The name "${name}" is already in use`); + } + + (this as any)[name] = system; + + this._systemsHash[name] = system; + + for (const i in this.runners) + { + this.runners[i].add(system); + } + + /** + * Fired after rendering finishes. + * @event PIXI.Renderer#postrender + */ + + /** + * Fired before rendering starts. + * @event PIXI.Renderer#prerender + */ + + /** + * Fired when the WebGL context is set. + * @event PIXI.Renderer#context + * @param {WebGLRenderingContext} gl - WebGL context. + */ + + return this; + } + + /** + * A function that will run a runner and call the runners function but pass in different options + * to each system based on there name. + * + * eg if you have two systems added called `systemA` and `systemB` you could call do the following: + * + * ``` + * system.emitWithCustomOptions(init, { + * systemA: {...optionsForA}, + * systemB: {...optionsForB} + * }) + * + * init would be called on system A passing options.A and init would be called on system B passing options.B + * ``` + * @param runner - the runner to target + * @param options - key value options for each system + */ + emitWithCustomOptions(runner: Runner, options: Record): void + { + const systemHashKeys = Object.keys(this._systemsHash); + + runner.items.forEach((system) => + { + // I know this does not need to be a performant function so it.. isn't! + // its only used for init and destroy.. we can refactor if required.. + const systemName = systemHashKeys.find((systemId) => this._systemsHash[systemId] === system); + + system[runner.name](options[systemName]); + }); + } + + /** destroy the all runners and systems. Its apps job to */ + destroy(): void + { + Object.values(this.runners).forEach((runner) => + { + runner.destroy(); + }); + + this._systemsHash = {}; + } + + // TODO implement! + // removeSystem(ClassRef: ISystemConstructor, name: string): void + // { + + // } +} diff --git a/packages/core/src/systems.ts b/packages/core/src/systems.ts index d0c573b6019..e97b7ed096d 100644 --- a/packages/core/src/systems.ts +++ b/packages/core/src/systems.ts @@ -12,3 +12,9 @@ export * from './shader/ShaderSystem'; export * from './state/StateSystem'; export * from './textures/TextureGCSystem'; export * from './textures/TextureSystem'; +export * from './renderTexture/GenerateTextureSystem'; +export * from './background/BackgroundSystem'; +export * from './view/ViewSystem'; +export * from './plugin/PluginSystem'; +export * from './system/SystemManager'; +export * from './startup/StartupSystem'; diff --git a/packages/core/src/textures/BaseTexture.ts b/packages/core/src/textures/BaseTexture.ts index e1e2ecf7d63..fe36bed35d6 100644 --- a/packages/core/src/textures/BaseTexture.ts +++ b/packages/core/src/textures/BaseTexture.ts @@ -1,11 +1,11 @@ import { BaseTextureCache, EventEmitter, isPow2, TextureCache, uid } from '@pixi/utils'; -import { FORMATS, SCALE_MODES, TARGETS, TYPES, ALPHA_MODES, MIPMAP_MODES, WRAP_MODES } from '@pixi/constants'; +import { FORMATS, SCALE_MODES, TARGETS, TYPES, ALPHA_MODES } from '@pixi/constants'; import { Resource } from './resources/Resource'; import { BufferResource } from './resources/BufferResource'; import { autoDetectResource } from './resources/autoDetectResource'; import { settings } from '@pixi/settings'; -import type { MSAA_QUALITY } from '@pixi/constants'; +import type { MSAA_QUALITY, MIPMAP_MODES, WRAP_MODES } from '@pixi/constants'; import type { IAutoDetectOptions } from './resources/autoDetectResource'; import type { GLTexture } from './GLTexture'; @@ -15,9 +15,10 @@ const defaultBufferOptions = { alphaMode: ALPHA_MODES.NPM, }; -export type ImageSource = HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|ImageBitmap; +export type ImageSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap; -export interface IBaseTextureOptions { +export interface IBaseTextureOptions +{ alphaMode?: ALPHA_MODES; mipmap?: MIPMAP_MODES; anisotropicLevel?: number; @@ -40,7 +41,6 @@ export interface BaseTexture extends GlobalMixins.BaseTexture, EventEmitter {} * A Texture stores the information that represents an image. * All textures have a base texture, which contains information about the source. * Therefore you can have many textures all using a single BaseTexture - * * @memberof PIXI * @typeParam R - The BaseTexture's Resource type. * @typeParam RO - The options for constructing resource. @@ -49,21 +49,18 @@ export class BaseTexture { /** * The width of the base texture set when the image has loaded - * * @readonly */ public width: number; /** * The height of the base texture set when the image has loaded - * * @readonly */ public height: number; /** * The resolution / device pixel ratio of the texture - * * @readonly * @default PIXI.settings.RESOLUTION */ @@ -71,7 +68,6 @@ export class BaseTexture /** * How to treat premultiplied alpha, see {@link PIXI.ALPHA_MODES}. - * * @member {PIXI.ALPHA_MODES} * @default PIXI.ALPHA_MODES.UNPACK */ @@ -79,7 +75,6 @@ export class BaseTexture /** * Anisotropic filtering level of texture - * * @member {number} * @default PIXI.settings.ANISOTROPIC_LEVEL */ @@ -87,35 +82,30 @@ export class BaseTexture /** * The pixel format of the texture - * * @default PIXI.FORMATS.RGBA */ public format?: FORMATS; /** * The type of resource data - * * @default PIXI.TYPES.UNSIGNED_BYTE */ public type?: TYPES; /** * The target type - * * @default PIXI.TARGETS.TEXTURE_2D */ public target?: TARGETS; /** * Global unique identifier for this BaseTexture - * * @protected */ public readonly uid: number; /** * Used by automatic texture Garbage Collection, stores last GC tick when it was bound - * * @protected */ touched: number; @@ -123,7 +113,6 @@ export class BaseTexture /** * Whether or not the texture is a power of two, try to use power of two textures as much * as you can - * * @readonly * @default false */ @@ -131,7 +120,6 @@ export class BaseTexture /** * The map of render context textures where this is bound - * * @private */ _glTextures: { [key: number]: GLTexture }; @@ -139,21 +127,18 @@ export class BaseTexture /** * Used by TextureSystem to only update texture to the GPU when needed. * Please call `update()` to increment it. - * * @readonly */ dirtyId: number; /** * Used by TextureSystem to only update texture style when needed. - * * @protected */ dirtyStyleId: number; /** * Currently default cache ID. - * * @member {string} */ public cacheId: string; @@ -168,7 +153,6 @@ export class BaseTexture /** * The collection of alternative cache ids, since some BaseTextures * can have more than one ID, short name and longer full URL - * * @member {Array} * @readonly */ @@ -176,7 +160,6 @@ export class BaseTexture /** * Flag if BaseTexture has been destroyed. - * * @member {boolean} * @readonly */ @@ -186,7 +169,6 @@ export class BaseTexture * The resource used by this BaseTexture, there can only * be one resource per BaseTexture, but textures can share * resources. - * * @member {PIXI.Resource} * @readonly */ @@ -194,21 +176,18 @@ export class BaseTexture /** * Number of the texture batch, used by multi-texture renderers - * * @member {number} */ _batchEnabled: number; /** * Location inside texture batch, used by multi-texture renderers - * * @member {number} */ _batchLocation: number; /** * Whether its a part of another texture, handled by ArrayResource or CubeResource - * * @member {PIXI.BaseTexture} */ parentTextureArray: BaseTexture; @@ -255,14 +234,14 @@ export class BaseTexture this.resolution = resolution || settings.RESOLUTION; this.width = Math.round((width || 0) * this.resolution) / this.resolution; this.height = Math.round((height || 0) * this.resolution) / this.resolution; - this._mipmap = mipmap !== undefined ? mipmap : settings.MIPMAP_TEXTURES; - this.anisotropicLevel = anisotropicLevel !== undefined ? anisotropicLevel : settings.ANISOTROPIC_LEVEL; + this._mipmap = mipmap ?? settings.MIPMAP_TEXTURES; + this.anisotropicLevel = anisotropicLevel ?? settings.ANISOTROPIC_LEVEL; this._wrapMode = wrapMode || settings.WRAP_MODE; - this._scaleMode = scaleMode !== undefined ? scaleMode : settings.SCALE_MODE; + this._scaleMode = scaleMode ?? settings.SCALE_MODE; this.format = format || FORMATS.RGBA; this.type = type || TYPES.UNSIGNED_BYTE; this.target = target || TARGETS.TEXTURE_2D; - this.alphaMode = alphaMode !== undefined ? alphaMode : ALPHA_MODES.UNPACK; + this.alphaMode = alphaMode ?? ALPHA_MODES.UNPACK; this.uid = uid(); this.touched = 0; @@ -284,7 +263,6 @@ export class BaseTexture /** * Fired when a not-immediately-available source finishes loading. - * * @protected * @event PIXI.BaseTexture#loaded * @param {PIXI.BaseTexture} baseTexture - Resource loaded. @@ -292,7 +270,6 @@ export class BaseTexture /** * Fired when a not-immediately-available source fails to load. - * * @protected * @event PIXI.BaseTexture#error * @param {PIXI.BaseTexture} baseTexture - Resource errored. @@ -301,7 +278,6 @@ export class BaseTexture /** * Fired when BaseTexture is updated. - * * @protected * @event PIXI.BaseTexture#loaded * @param {PIXI.BaseTexture} baseTexture - Resource loaded. @@ -309,7 +285,6 @@ export class BaseTexture /** * Fired when BaseTexture is updated. - * * @protected * @event PIXI.BaseTexture#update * @param {PIXI.BaseTexture} baseTexture - Instance of texture being updated. @@ -317,7 +292,6 @@ export class BaseTexture /** * Fired when BaseTexture is destroyed. - * * @protected * @event PIXI.BaseTexture#dispose * @param {PIXI.BaseTexture} baseTexture - Instance of texture being destroyed. @@ -329,7 +303,6 @@ export class BaseTexture /** * Pixel width of the source of this texture - * * @readonly */ get realWidth(): number @@ -339,7 +312,6 @@ export class BaseTexture /** * Pixel height of the source of this texture - * * @readonly */ get realHeight(): number @@ -349,7 +321,6 @@ export class BaseTexture /** * Mipmap mode of the texture, affects downscaled images - * * @default PIXI.settings.MIPMAP_TEXTURES */ get mipmap(): MIPMAP_MODES @@ -367,7 +338,6 @@ export class BaseTexture /** * The scale mode to apply when scaling this texture - * * @default PIXI.settings.SCALE_MODE */ get scaleMode(): SCALE_MODES @@ -385,7 +355,6 @@ export class BaseTexture /** * How the texture wraps - * * @default PIXI.settings.WRAP_MODE */ get wrapMode(): WRAP_MODES @@ -403,7 +372,6 @@ export class BaseTexture /** * Changes style options of BaseTexture - * * @param scaleMode - Pixi scalemode * @param mipmap - enable mipmaps * @returns - this @@ -434,7 +402,6 @@ export class BaseTexture /** * Changes w/h/resolution. Texture becomes valid if width and height are greater than zero. - * * @param desiredWidth - Desired visual width * @param desiredHeight - Desired visual height * @param resolution - Optionally set resolution @@ -449,7 +416,6 @@ export class BaseTexture /** * Sets real size of baseTexture, preserves current resolution. - * * @param realWidth - Full rendered width * @param realHeight - Full rendered height * @param resolution - Optionally set resolution @@ -468,7 +434,6 @@ export class BaseTexture /** * Refresh check for isPowerOfTwo texture based on size - * * @private */ protected _refreshPOT(): void @@ -478,7 +443,6 @@ export class BaseTexture /** * Changes resolution - * * @param resolution - res * @returns - this */ @@ -507,7 +471,6 @@ export class BaseTexture /** * Sets the resource if it wasn't set. Throws error if resource already present - * * @param resource - that is managing this BaseTexture * @returns - this */ @@ -552,7 +515,6 @@ export class BaseTexture /** * Handle errors with resources. - * * @private * @param event - Error event emitted. */ @@ -601,7 +563,6 @@ export class BaseTexture * Frees the texture from WebGL memory without destroying this texture object. * This means you can still use the texture later which will upload it to GPU * memory again. - * * @fires PIXI.BaseTexture#dispose */ dispose(): void @@ -620,16 +581,15 @@ export class BaseTexture * The source can be - image url, image element, canvas element. If the * source is an image url or an image element and not in the base texture * cache, it will be created and loaded. - * * @static - * @param {string|HTMLImageElement|HTMLCanvasElement|SVGElement|HTMLVideoElement} source - The + * @param {string|string[]|HTMLImageElement|HTMLCanvasElement|SVGElement|HTMLVideoElement} source - The * source to create base texture from. * @param options - See {@link PIXI.BaseTexture}'s constructor for options. * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}. * @returns {PIXI.BaseTexture} The new base texture. */ - static from(source: ImageSource|string, + static from(source: ImageSource | string | string[], options?: IBaseTextureOptions, strict = settings.STRICT_TEXTURE_CACHE): BaseTexture { const isFrame = typeof source === 'string'; @@ -643,7 +603,7 @@ export class BaseTexture { if (!(source as any)._pixiId) { - const prefix = (options && options.pixiIdPrefix) || 'pixiid'; + const prefix = options?.pixiIdPrefix || 'pixiid'; (source as any)._pixiId = `${prefix}_${uid()}`; } @@ -672,15 +632,18 @@ export class BaseTexture /** * Create a new BaseTexture with a BufferResource from a Float32Array. * RGBA values are floats from 0 to 1. - * * @param {Float32Array|Uint8Array} buffer - The optional array to use, if no data * is provided, a new Float32Array is created. * @param width - Width of the resource * @param height - Height of the resource * @param options - See {@link PIXI.BaseTexture}'s constructor for options. - * @return - The resulting new BaseTexture + * Default properties are different from the constructor's defaults. + * @param {PIXI.FORMATS} [options.format=PIXI.FORMATS.RGBA] - GL format type + * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.NPM] - Image alpha, not premultiplied by default + * @param {PIXI.SCALE_MODES} [options.scaleMode=PIXI.SCALE_MODES.NEAREST] - Scale mode, pixelating by default + * @returns - The resulting new BaseTexture */ - static fromBuffer(buffer: Float32Array|Uint8Array, + static fromBuffer(buffer: Float32Array | Uint8Array, width: number, height: number, options?: IBaseTextureOptions): BaseTexture { buffer = buffer || new Float32Array(width * height * 4); @@ -693,8 +656,6 @@ export class BaseTexture /** * Adds a BaseTexture to the global BaseTextureCache. This cache is shared across the whole PIXI object. - * - * * @param {PIXI.BaseTexture} baseTexture - The BaseTexture to add to the cache. * @param {string} id - The id that the BaseTexture will be stored against. */ @@ -702,7 +663,7 @@ export class BaseTexture { if (id) { - if (baseTexture.textureCacheIds.indexOf(id) === -1) + if (!baseTexture.textureCacheIds.includes(id)) { baseTexture.textureCacheIds.push(id); } @@ -719,11 +680,10 @@ export class BaseTexture /** * Remove a BaseTexture from the global BaseTextureCache. - * * @param {string|PIXI.BaseTexture} baseTexture - id of a BaseTexture to be removed, or a BaseTexture instance itself. - * @return {PIXI.BaseTexture|null} The BaseTexture that was removed. + * @returns {PIXI.BaseTexture|null} The BaseTexture that was removed. */ - static removeFromCache(baseTexture: string | BaseTexture): BaseTexture|null + static removeFromCache(baseTexture: string | BaseTexture): BaseTexture | null { if (typeof baseTexture === 'string') { @@ -743,7 +703,7 @@ export class BaseTexture return baseTextureFromCache; } } - else if (baseTexture && baseTexture.textureCacheIds) + else if (baseTexture?.textureCacheIds) { for (let i = 0; i < baseTexture.textureCacheIds.length; ++i) { diff --git a/packages/core/src/textures/GLTexture.ts b/packages/core/src/textures/GLTexture.ts index 28545a94eda..2770c957c60 100644 --- a/packages/core/src/textures/GLTexture.ts +++ b/packages/core/src/textures/GLTexture.ts @@ -2,7 +2,6 @@ import { FORMATS, TYPES } from '@pixi/constants'; /** * Internal texture for WebGL context. - * * @memberof PIXI */ export class GLTexture diff --git a/packages/core/src/textures/Texture.ts b/packages/core/src/textures/Texture.ts index 126b6df7cbb..b2cd9d062d2 100644 --- a/packages/core/src/textures/Texture.ts +++ b/packages/core/src/textures/Texture.ts @@ -1,6 +1,6 @@ import { BaseTexture } from './BaseTexture'; import { ImageResource } from './resources/ImageResource'; -import { CanvasResource } from './resources/CanvasResource'; +import type { CanvasResource } from './resources/CanvasResource'; import { TextureUvs } from './TextureUvs'; import { settings } from '@pixi/settings'; import { Rectangle, Point } from '@pixi/math'; @@ -14,10 +14,22 @@ import type { TextureMatrix } from './TextureMatrix'; const DEFAULT_UVS = new TextureUvs(); -export type TextureSource = string|BaseTexture|ImageSource; +export type TextureSource = string | BaseTexture | ImageSource; export interface Texture extends GlobalMixins.Texture, EventEmitter {} +/** + * Used to remove listeners from WHITE and EMPTY Textures + * @ignore + */ +function removeAllHandlers(tex: any): void +{ + tex.destroy = function _emptyDestroy(): void { /* empty */ }; + tex.on = function _emptyOn(): void { /* empty */ }; + tex.once = function _emptyOnce(): void { /* empty */ }; + tex.emit = function _emptyEmit(): void { /* empty */ }; +} + /** * A texture stores the information that represents an image or part of an image. * @@ -43,7 +55,6 @@ export interface Texture extends GlobalMixins.Texture, EventEmitter {} * //sprite1._textureID should not be undefined if the texture has finished processing the SVG file * ``` * You can use a ticker or rAF to ensure your sprites load the finished textures after processing. See issue #3068. - * * @memberof PIXI * @typeParam R - The BaseTexture's Resource type. */ @@ -85,22 +96,17 @@ export class Texture extends EventEmitter /** * Anchor point that is used as default if sprite is created with this texture. * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point. - * * @default {0,0} */ public defaultAnchor: Point; - /** - * Default TextureMatrix instance for this texture. - * By default, that object is not created because its heavy. - */ + /** Default TextureMatrix instance for this texture. By default, that object is not created because its heavy. */ public uvMatrix: TextureMatrix; protected _rotate: number; /** * Update ID is observed by sprites and TextureMatrix instances. * Call updateUvs() to increment it. - * * @protected */ _updateID: number; @@ -113,7 +119,6 @@ export class Texture extends EventEmitter /** * The WebGL UV data cache. Can be used as quad UV. - * * @protected */ _uvs: TextureUvs; @@ -217,7 +222,6 @@ export class Texture extends EventEmitter /** * Called when the base texture is updated - * * @protected * @param baseTexture - The base texture. */ @@ -247,7 +251,6 @@ export class Texture extends EventEmitter /** * Destroys this texture - * * @param [destroyBase=false] - Whether to destroy the base texture as well */ destroy(destroyBase?: boolean): void @@ -260,7 +263,7 @@ export class Texture extends EventEmitter // delete the texture if it exists in the texture cache.. // this only needs to be removed if the base texture is actually destroyed too.. - if (resource && resource.url && TextureCache[resource.url]) + if (resource?.url && TextureCache[resource.url]) { Texture.removeFromCache(resource.url); } @@ -287,8 +290,7 @@ export class Texture extends EventEmitter /** * Creates a new texture object that acts the same as this one. - * - * @return - The new texture + * @returns - The new texture */ clone(): Texture { @@ -297,7 +299,7 @@ export class Texture extends EventEmitter const clonedTexture = new Texture(this.baseTexture, !this.noFrame && clonedFrame, clonedOrig, - this.trim && this.trim.clone(), + this.trim?.clone(), this.rotate, this.defaultAnchor ); @@ -329,15 +331,15 @@ export class Texture extends EventEmitter /** * Helper function that creates a new Texture based on the source you provide. * The source can be - frame id, image url, video url, canvas element, video element, base texture - * * @param {string|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|PIXI.BaseTexture} source - - * Source to create texture from + * Source or array of sources to create texture from * @param options - See {@link PIXI.BaseTexture}'s constructor for options. * @param {string} [options.pixiIdPrefix=pixiid] - If a source has no id, this is the prefix of the generated id * @param {boolean} [strict] - Enforce strict-mode, see {@link PIXI.settings.STRICT_TEXTURE_CACHE}. - * @return {PIXI.Texture} The newly created texture + * @returns {PIXI.Texture} The newly created texture */ - static from(source: TextureSource, options: IBaseTextureOptions = {}, + static from(source: TextureSource | TextureSource[], + options: IBaseTextureOptions = {}, strict = settings.STRICT_TEXTURE_CACHE): Texture { const isFrame = typeof source === 'string'; @@ -351,7 +353,7 @@ export class Texture extends EventEmitter { if (!source.cacheId) { - const prefix = (options && options.pixiIdPrefix) || 'pixiid'; + const prefix = options?.pixiIdPrefix || 'pixiid'; source.cacheId = `${prefix}-${uid()}`; BaseTexture.addToCache(source, source.cacheId); @@ -363,7 +365,7 @@ export class Texture extends EventEmitter { if (!(source as any)._pixiId) { - const prefix = (options && options.pixiIdPrefix) || 'pixiid'; + const prefix = options?.pixiIdPrefix || 'pixiid'; (source as any)._pixiId = `${prefix}_${uid()}`; } @@ -407,13 +409,12 @@ export class Texture extends EventEmitter * Useful for loading textures via URLs. Use instead of `Texture.from` because * it does a better job of handling failed URLs more effectively. This also ignores * `PIXI.settings.STRICT_TEXTURE_CACHE`. Works for Videos, SVGs, Images. - * - * @param url - The remote URL to load. + * @param url - The remote URL or array of URLs to load. * @param options - Optional options to include - * @return - A Promise that resolves to a Texture. + * @returns - A Promise that resolves to a Texture. */ static fromURL( - url: string, options?: IBaseTextureOptions): Promise> + url: string | string[], options?: IBaseTextureOptions): Promise> { const resourceOptions = Object.assign({ autoLoad: false }, options?.resourceOptions); const texture = Texture.from(url, Object.assign({ resourceOptions }, options), false); @@ -432,15 +433,14 @@ export class Texture extends EventEmitter /** * Create a new Texture with a BufferResource from a Float32Array. * RGBA values are floats from 0 to 1. - * * @param {Float32Array|Uint8Array} buffer - The optional array to use, if no data * is provided, a new Float32Array is created. * @param width - Width of the resource * @param height - Height of the resource * @param options - See {@link PIXI.BaseTexture}'s constructor for options. - * @return - The resulting new BaseTexture + * @returns - The resulting new BaseTexture */ - static fromBuffer(buffer: Float32Array|Uint8Array, + static fromBuffer(buffer: Float32Array | Uint8Array, width: number, height: number, options?: IBaseTextureOptions): Texture { return new Texture(BaseTexture.fromBuffer(buffer, width, height, options)); @@ -448,14 +448,14 @@ export class Texture extends EventEmitter /** * Create a texture from a source and add to the cache. - * * @param {HTMLImageElement|HTMLCanvasElement|string} source - The input source. * @param imageUrl - File name of texture, for cache and resolving resolution. * @param name - Human readable name for the texture cache. If no name is * specified, only `imageUrl` will be used as the cache ID. - * @return - Output texture + * @param options + * @returns - Output texture */ - static fromLoader(source: HTMLImageElement|HTMLCanvasElement|string, + static fromLoader(source: HTMLImageElement | HTMLCanvasElement | string, imageUrl: string, name?: string, options?: IBaseTextureOptions): Promise> { const baseTexture = new BaseTexture(source, Object.assign({ @@ -504,7 +504,6 @@ export class Texture extends EventEmitter /** * Adds a Texture to the global TextureCache. This cache is shared across the whole PIXI object. - * * @param texture - The Texture to add to the cache. * @param id - The id that the Texture will be stored against. */ @@ -512,7 +511,7 @@ export class Texture extends EventEmitter { if (id) { - if (texture.textureCacheIds.indexOf(id) === -1) + if (!texture.textureCacheIds.includes(id)) { texture.textureCacheIds.push(id); } @@ -529,11 +528,10 @@ export class Texture extends EventEmitter /** * Remove a Texture from the global TextureCache. - * * @param texture - id of a Texture to be removed, or a Texture instance itself - * @return - The Texture that was removed + * @returns - The Texture that was removed */ - static removeFromCache(texture: string|Texture): Texture|null + static removeFromCache(texture: string | Texture): Texture | null { if (typeof texture === 'string') { @@ -553,7 +551,7 @@ export class Texture extends EventEmitter return textureFromCache; } } - else if (texture && texture.textureCacheIds) + else if (texture?.textureCacheIds) { for (let i = 0; i < texture.textureCacheIds.length; ++i) { @@ -574,7 +572,6 @@ export class Texture extends EventEmitter /** * Returns resolution of baseTexture - * * @readonly */ get resolution(): number @@ -663,53 +660,41 @@ export class Texture extends EventEmitter return this.baseTexture; } - static readonly EMPTY: Texture; - static readonly WHITE: Texture; -} + private static _EMPTY: Texture; + private static _WHITE: Texture; -function createWhiteTexture(): Texture -{ - const canvas = document.createElement('canvas'); + /** An empty texture, used often to not have to create multiple empty textures. Can not be destroyed. */ + public static get EMPTY(): Texture + { + if (!Texture._EMPTY) + { + Texture._EMPTY = new Texture(new BaseTexture()); + removeAllHandlers(Texture._EMPTY); + removeAllHandlers(Texture._EMPTY.baseTexture); + } - canvas.width = 16; - canvas.height = 16; + return Texture._EMPTY; + } - const context = canvas.getContext('2d'); + /** A white texture of 16x16 size, used for graphics and other things Can not be destroyed. */ + public static get WHITE(): Texture + { + if (!Texture._WHITE) + { + const canvas = settings.ADAPTER.createCanvas(16, 16); + const context = canvas.getContext('2d'); - context.fillStyle = 'white'; - context.fillRect(0, 0, 16, 16); + canvas.width = 16; + canvas.height = 16; + context.fillStyle = 'white'; + context.fillRect(0, 0, 16, 16); - return new Texture(new BaseTexture(new CanvasResource(canvas))); -} + Texture._WHITE = new Texture(BaseTexture.from(canvas)); + removeAllHandlers(Texture._WHITE); + removeAllHandlers(Texture._WHITE.baseTexture); + } -function removeAllHandlers(tex: any): void -{ - tex.destroy = function _emptyDestroy(): void { /* empty */ }; - tex.on = function _emptyOn(): void { /* empty */ }; - tex.once = function _emptyOnce(): void { /* empty */ }; - tex.emit = function _emptyEmit(): void { /* empty */ }; + return Texture._WHITE; + } } -/** - * An empty texture, used often to not have to create multiple empty textures. - * Can not be destroyed. - * - * @static - * @constant - * @member {PIXI.Texture} - */ -(Texture as any).EMPTY = new Texture(new BaseTexture()); -removeAllHandlers(Texture.EMPTY); -removeAllHandlers(Texture.EMPTY.baseTexture); - -/** - * A white texture of 16x16 size, used for graphics and other things - * Can not be destroyed. - * - * @static - * @constant - * @member {PIXI.Texture} - */ -(Texture as any).WHITE = createWhiteTexture(); -removeAllHandlers(Texture.WHITE); -removeAllHandlers(Texture.WHITE.baseTexture); diff --git a/packages/core/src/textures/TextureGCSystem.ts b/packages/core/src/textures/TextureGCSystem.ts index fe17f8800e3..cfc09cd8f8f 100644 --- a/packages/core/src/textures/TextureGCSystem.ts +++ b/packages/core/src/textures/TextureGCSystem.ts @@ -1,12 +1,15 @@ import { GC_MODES } from '@pixi/constants'; import { settings } from '@pixi/settings'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Renderer } from '../Renderer'; import type { Texture } from './Texture'; import type { RenderTexture } from '../renderTexture/RenderTexture'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; -export interface IUnloadableTexture { +export interface IUnloadableTexture +{ _texture: Texture | RenderTexture; children: IUnloadableTexture[]; } @@ -14,42 +17,42 @@ export interface IUnloadableTexture { /** * System plugin to the renderer to manage texture garbage collection on the GPU, * ensuring that it does not get clogged up with textures that are no longer being used. - * * @memberof PIXI */ export class TextureGCSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'textureGC', + }; + /** * Count - * * @readonly */ public count: number; /** * Check count - * * @readonly */ public checkCount: number; /** * Maximum idle time, in seconds - * * @see PIXI.settings.GC_MAX_IDLE */ public maxIdle: number; /** * Maximum number of item to check - * * @see PIXI.settings.GC_MAX_CHECK_COUNT */ public checkCountMax: number; /** * Current garbage collection mode - * * @see PIXI.settings.GC_MODE */ public mode: GC_MODES; @@ -73,7 +76,7 @@ export class TextureGCSystem implements ISystem */ protected postrender(): void { - if (!this.renderer.renderingToScreen) + if (!this.renderer.objectRenderer.renderingToScreen) { return; } @@ -136,7 +139,6 @@ export class TextureGCSystem implements ISystem /** * Removes all the textures within the specified displayObject and its children from the GPU - * * @param {PIXI.DisplayObject} displayObject - the displayObject to remove the textures from. */ unload(displayObject: IUnloadableTexture): void @@ -161,3 +163,5 @@ export class TextureGCSystem implements ISystem this.renderer = null; } } + +extensions.add(TextureGCSystem); diff --git a/packages/core/src/textures/TextureMatrix.ts b/packages/core/src/textures/TextureMatrix.ts index 4c0c3fb80f2..013628309a3 100644 --- a/packages/core/src/textures/TextureMatrix.ts +++ b/packages/core/src/textures/TextureMatrix.ts @@ -14,7 +14,6 @@ const tempMat = new Matrix(); * * Takes track of Texture changes through `_lastTextureID` private field. * Use `update()` method call to track it from outside. - * * @see PIXI.Texture * @see PIXI.Mesh * @see PIXI.TilingSprite @@ -24,7 +23,6 @@ export class TextureMatrix { /** * Matrix operation that converts texture region coords to texture coords - * * @readonly */ public mapCoord: Matrix; @@ -33,7 +31,6 @@ export class TextureMatrix * Changes frame clamping * Works with TilingSprite and Mesh * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders - * * @default 0 */ public clampOffset: number; @@ -42,7 +39,6 @@ export class TextureMatrix * Changes frame clamping * Works with TilingSprite and Mesh * Change to -0.5 to add a pixel to the edge, recommended for transparent trimmed textures in atlas - * * @default 0.5 */ public clampMargin: number; @@ -53,22 +49,17 @@ export class TextureMatrix */ readonly uClampFrame: Float32Array; - /** - * Normalized clamp offset. - * Calculated based on clampOffset. - */ + /** Normalized clamp offset. Calculated based on clampOffset. */ readonly uClampOffset: Float32Array; /** * Tracks Texture frame changes. - * * @protected */ _textureID: number; /** * Tracks Texture frame changes. - * * @protected */ _updateID: number; @@ -76,7 +67,6 @@ export class TextureMatrix /** * If texture size is the same as baseTexture. - * * @default false * @readonly */ @@ -115,7 +105,6 @@ export class TextureMatrix /** * Multiplies uvs array to transform - * * @param uvs - mesh uvs * @param [out=uvs] - output * @returns - output @@ -143,7 +132,6 @@ export class TextureMatrix /** * Updates matrices if texture was changed. - * * @param [forceUpdate=false] - if true, matrices will be updated any case * @returns - Whether or not it was updated */ diff --git a/packages/core/src/textures/TextureSystem.ts b/packages/core/src/textures/TextureSystem.ts index 2a2a8b7cd1a..17ce2497b7e 100644 --- a/packages/core/src/textures/TextureSystem.ts +++ b/packages/core/src/textures/TextureSystem.ts @@ -4,28 +4,34 @@ import { GLTexture } from './GLTexture'; import { removeItems } from '@pixi/utils'; import { MIPMAP_MODES, WRAP_MODES, SCALE_MODES, TYPES, SAMPLER_TYPES } from '@pixi/constants'; -import type { ISystem } from '../ISystem'; +import type { ISystem } from '../system/ISystem'; import type { Texture } from './Texture'; -import type { IRenderingContext } from '../IRenderingContext'; + import type { Renderer } from '../Renderer'; +import type { IRenderingContext } from '../IRenderer'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; /** * System plugin to the renderer to manage textures. - * * @memberof PIXI */ export class TextureSystem implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + type: ExtensionType.RendererSystem, + name: 'texture', + }; + /** * Bound textures. - * * @readonly */ public boundTextures: BaseTexture[]; /** * List of managed textures. - * * @readonly */ public managedTextures: Array; @@ -39,21 +45,18 @@ export class TextureSystem implements ISystem /** * BaseTexture value that shows that we don't know what is bound. - * * @readonly */ protected unknownTexture: BaseTexture; /** * Did someone temper with textures state? We'll overwrite them when we need to unbind something. - * * @private */ protected _unknownBoundTextures: boolean; /** * Current location. - * * @readonly */ currentLocation: number; @@ -129,11 +132,10 @@ export class TextureSystem implements ISystem * Bind a texture to a specific location * * If you want to unbind something, please use `unbind(texture)` instead of `bind(null, textureLocation)` - * - * @param texture_ - Texture to bind + * @param texture - Texture to bind * @param [location=0] - Location to bind at */ - bind(texture: Texture|BaseTexture, location = 0): void + bind(texture: Texture | BaseTexture, location = 0): void { const { gl } = this; @@ -141,7 +143,7 @@ export class TextureSystem implements ISystem // cannot bind partial texture // TODO: report a warning - if (texture && texture.valid && !texture.parentTextureArray) + if (texture?.valid && !texture.parentTextureArray) { texture.touched = this.renderer.textureGC.count; @@ -183,11 +185,7 @@ export class TextureSystem implements ISystem } } - /** - * Resets texture location and bound textures - * - * Actual `bind(null, i)` calls will be performed at next `unbind()` call - */ + /** Resets texture location and bound textures Actual `bind(null, i)` calls will be performed at next `unbind()` call */ reset(): void { this._unknownBoundTextures = true; @@ -202,7 +200,6 @@ export class TextureSystem implements ISystem /** * Unbind a texture. - * * @param texture - Texture to bind */ unbind(texture?: BaseTexture): void @@ -242,7 +239,6 @@ export class TextureSystem implements ISystem /** * Ensures that current boundTextures all have FLOAT sampler type, * see {@link PIXI.SAMPLER_TYPES} for explanation. - * * @param maxTextures - number of locations to check */ ensureSamplerType(maxTextures: number): void @@ -272,7 +268,6 @@ export class TextureSystem implements ISystem /** * Initialize a texture - * * @private * @param texture - Texture to initialize */ @@ -309,7 +304,6 @@ export class TextureSystem implements ISystem /** * Update a texture - * * @private * @param {PIXI.BaseTexture} texture - Texture to initialize */ @@ -326,7 +320,7 @@ export class TextureSystem implements ISystem this.initTextureType(texture, glTexture); - if (texture.resource && texture.resource.upload(renderer, texture, glTexture)) + if (texture.resource?.upload(renderer, texture, glTexture)) { // texture is uploaded, dont do anything! if (glTexture.samplerType !== SAMPLER_TYPES.FLOAT) @@ -369,12 +363,11 @@ export class TextureSystem implements ISystem /** * Deletes the texture from WebGL - * * @private - * @param texture_ - the texture to destroy + * @param texture - the texture to destroy * @param [skipRemove=false] - Whether to skip removing the texture from the TextureManager. */ - destroyTexture(texture: BaseTexture|Texture, skipRemove?: boolean): void + destroyTexture(texture: BaseTexture | Texture, skipRemove?: boolean): void { const { gl } = this; @@ -403,7 +396,6 @@ export class TextureSystem implements ISystem /** * Update texture style such as mipmap flag - * * @private * @param {PIXI.BaseTexture} texture - Texture to update */ @@ -434,7 +426,7 @@ export class TextureSystem implements ISystem glTexture.wrapMode = texture.wrapMode; } - if (texture.resource && texture.resource.style(this.renderer, texture, glTexture)) + if (texture.resource?.style(this.renderer, texture, glTexture)) { // style is set, dont do anything! } @@ -448,7 +440,6 @@ export class TextureSystem implements ISystem /** * Set style for texture - * * @private * @param texture - Texture to update * @param glTexture @@ -493,3 +484,5 @@ export class TextureSystem implements ISystem this.renderer = null; } } + +extensions.add(TextureSystem); diff --git a/packages/core/src/textures/TextureUvs.ts b/packages/core/src/textures/TextureUvs.ts index 4f90e1e6f02..6e796c6f8e0 100644 --- a/packages/core/src/textures/TextureUvs.ts +++ b/packages/core/src/textures/TextureUvs.ts @@ -13,7 +13,6 @@ import type { Rectangle, ISize } from '@pixi/math'; * | Top-Right | `(x1,y1)` | * | Bottom-Right | `(x2,y2)` | * | Bottom-Left | `(x3,y3)` | - * * @protected * @memberof PIXI */ @@ -60,7 +59,6 @@ export class TextureUvs /** * Sets the texture Uvs based on the given frame information. - * * @protected * @param frame - The frame of the texture * @param baseFrame - The base frame of the texture diff --git a/packages/core/src/textures/resources/AbstractMultiResource.ts b/packages/core/src/textures/resources/AbstractMultiResource.ts index 85f9ea57929..aa4baf953be 100644 --- a/packages/core/src/textures/resources/AbstractMultiResource.ts +++ b/packages/core/src/textures/resources/AbstractMultiResource.ts @@ -1,13 +1,13 @@ import { Resource } from './Resource'; import { BaseTexture } from '../BaseTexture'; -import { ISize } from '@pixi/math'; -import { autoDetectResource, IAutoDetectOptions } from './autoDetectResource'; +import type { ISize } from '@pixi/math'; +import type { IAutoDetectOptions } from './autoDetectResource'; +import { autoDetectResource } from './autoDetectResource'; /** * Resource that can manage several resource (items) inside. * All resources need to have the same pixel size. * Parent class for CubeResource and ArrayResource - * * @memberof PIXI */ export abstract class AbstractMultiResource extends Resource @@ -17,21 +17,18 @@ export abstract class AbstractMultiResource extends Resource /** * Collection of partial baseTextures that correspond to resources. - * * @readonly */ items: Array; /** * Dirty IDs for each part. - * * @readonly */ itemDirtyIds: Array; /** * Promise when loading. - * * @default null */ private _load: Promise; @@ -72,7 +69,6 @@ export abstract class AbstractMultiResource extends Resource /** * Used from ArrayResource and CubeResource constructors. - * * @param resources - Can be resources, image elements, canvas, etc. , * length should be same as constructor length * @param options - Detect options for resources @@ -114,19 +110,17 @@ export abstract class AbstractMultiResource extends Resource /** * Set a baseTexture by ID - * * @param baseTexture * @param index - Zero-based index of resource to set - * @return - Instance for chaining + * @returns - Instance for chaining */ abstract addBaseTextureAt(baseTexture: BaseTexture, index: number): this; /** * Set a resource by ID - * * @param resource * @param index - Zero-based index of resource to set - * @return - Instance for chaining + * @returns - Instance for chaining */ addResourceAt(resource: Resource, index: number): this { @@ -146,7 +140,10 @@ export abstract class AbstractMultiResource extends Resource return this; } - /** Set the parent base texture. */ + /** + * Set the parent base texture. + * @param baseTexture + */ bind(baseTexture: BaseTexture): void { if (this.baseTexture !== null) @@ -162,7 +159,10 @@ export abstract class AbstractMultiResource extends Resource } } - /** Unset the parent base texture. */ + /** + * Unset the parent base texture. + * @param baseTexture + */ unbind(baseTexture: BaseTexture): void { super.unbind(baseTexture); @@ -176,8 +176,7 @@ export abstract class AbstractMultiResource extends Resource /** * Load all the resources simultaneously - * - * @return - When load is resolved + * @returns - When load is resolved */ load(): Promise { diff --git a/packages/core/src/textures/resources/ArrayResource.ts b/packages/core/src/textures/resources/ArrayResource.ts index 260321dd5e6..33b07eb26c6 100644 --- a/packages/core/src/textures/resources/ArrayResource.ts +++ b/packages/core/src/textures/resources/ArrayResource.ts @@ -1,6 +1,6 @@ import { AbstractMultiResource } from './AbstractMultiResource'; import { TARGETS } from '@pixi/constants'; -import { BaseTexture } from '../BaseTexture'; +import type { BaseTexture } from '../BaseTexture'; import type { BaseImageResource } from './BaseImageResource'; import type { Renderer } from '../../Renderer'; @@ -9,7 +9,6 @@ import type { ISize } from '@pixi/math'; /** * A resource that contains a number of sources. - * * @memberof PIXI */ export class ArrayResource extends AbstractMultiResource @@ -21,7 +20,7 @@ export class ArrayResource extends AbstractMultiResource * @param {number} [options.width] - Width of the resource * @param {number} [options.height] - Height of the resource */ - constructor(source: number|Array, options?: ISize) + constructor(source: number | Array, options?: ISize) { const { width, height } = options || {}; @@ -49,10 +48,9 @@ export class ArrayResource extends AbstractMultiResource /** * Set a baseTexture by ID, * ArrayResource just takes resource from it, nothing more - * * @param baseTexture * @param index - Zero-based index of resource to set - * @return - Instance for chaining + * @returns - Instance for chaining */ addBaseTextureAt(baseTexture: BaseTexture, index: number): this { @@ -68,7 +66,10 @@ export class ArrayResource extends AbstractMultiResource return this; } - /** Add binding */ + /** + * Add binding + * @param baseTexture + */ bind(baseTexture: BaseTexture): void { super.bind(baseTexture); @@ -78,7 +79,6 @@ export class ArrayResource extends AbstractMultiResource /** * Upload the resources to the GPU. - * * @param renderer * @param texture * @param glTexture diff --git a/packages/core/src/textures/resources/BaseImageResource.ts b/packages/core/src/textures/resources/BaseImageResource.ts index 85cabac3d84..3f523dd7c17 100644 --- a/packages/core/src/textures/resources/BaseImageResource.ts +++ b/packages/core/src/textures/resources/BaseImageResource.ts @@ -8,14 +8,12 @@ import type { GLTexture } from '../GLTexture'; /** * Base for all the image/canvas resources. - * * @memberof PIXI */ export class BaseImageResource extends Resource { /** * The source element. - * * @member {HTMLImageElement|HTMLCanvasElement|HTMLVideoElement|SVGElement} * @readonly */ @@ -24,7 +22,6 @@ export class BaseImageResource extends Resource /** * If set to `true`, will force `texImage2D` over `texSubImage2D` for uploading. * Certain types of media (e.g. video) using `texImage2D` is more performant. - * * @default false * @private */ @@ -47,14 +44,13 @@ export class BaseImageResource extends Resource /** * Set cross origin based detecting the url and the crossorigin - * * @param element - Element to apply crossOrigin * @param url - URL to check * @param crossorigin - Cross origin value to use */ - static crossOrigin(element: HTMLImageElement|HTMLVideoElement, url: string, crossorigin?: boolean|string): void + static crossOrigin(element: HTMLImageElement | HTMLVideoElement, url: string, crossorigin?: boolean | string): void { - if (crossorigin === undefined && url.indexOf('data:') !== 0) + if (crossorigin === undefined && !url.startsWith('data:')) { element.crossOrigin = determineCrossOrigin(url); } @@ -66,7 +62,6 @@ export class BaseImageResource extends Resource /** * Upload the texture to the GPU. - * * @param renderer - Upload to the renderer * @param baseTexture - Reference to parent texture * @param glTexture diff --git a/packages/core/src/textures/resources/BufferResource.ts b/packages/core/src/textures/resources/BufferResource.ts index 402adeeb2b3..691f66a9c33 100644 --- a/packages/core/src/textures/resources/BufferResource.ts +++ b/packages/core/src/textures/resources/BufferResource.ts @@ -11,16 +11,12 @@ import type { GLTexture } from '../GLTexture'; /** * Buffer resource with data of typed array. - * * @memberof PIXI */ export class BufferResource extends Resource { - /** - * Source array - * Cannot be {@code ClampedUint8Array} because it cant be uploaded to WebGL - */ - data: Float32Array|Uint8Array|Uint16Array|Int32Array|Uint32Array; + /** Source array Cannot be {@code ClampedUint8Array} because it cant be uploaded to WebGL */ + data: Float32Array | Uint8Array | Uint16Array | Int32Array | Uint32Array; /** * @param source - Source buffer @@ -28,7 +24,7 @@ export class BufferResource extends Resource * @param {number} options.width - Width of the texture * @param {number} options.height - Height of the texture */ - constructor(source: Float32Array|Uint8Array|Uint16Array|Int32Array|Uint32Array, options: ISize) + constructor(source: Float32Array | Uint8Array | Uint16Array | Int32Array | Uint32Array, options: ISize) { const { width, height } = options || {}; @@ -44,7 +40,6 @@ export class BufferResource extends Resource /** * Upload the texture to the GPU. - * * @param renderer - Upload to the renderer * @param baseTexture - Reference to parent texture * @param glTexture - glTexture @@ -102,11 +97,10 @@ export class BufferResource extends Resource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object - * @return {boolean} `true` if + * @returns {boolean} `true` if */ - static test(source: unknown): source is Float32Array|Uint8Array|Uint32Array + static test(source: unknown): source is Float32Array | Uint8Array | Uint32Array { return source instanceof Float32Array || source instanceof Uint8Array diff --git a/packages/core/src/textures/resources/CanvasResource.ts b/packages/core/src/textures/resources/CanvasResource.ts index 85ec31a6f95..f9826772b3b 100644 --- a/packages/core/src/textures/resources/CanvasResource.ts +++ b/packages/core/src/textures/resources/CanvasResource.ts @@ -6,7 +6,6 @@ import { BaseImageResource } from './BaseImageResource'; /** * Resource type for HTMLCanvasElement. - * * @memberof PIXI */ export class CanvasResource extends BaseImageResource @@ -22,11 +21,10 @@ export class CanvasResource extends BaseImageResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object - * @return {boolean} `true` if source is HTMLCanvasElement or OffscreenCanvas + * @returns {boolean} `true` if source is HTMLCanvasElement or OffscreenCanvas */ - static test(source: unknown): source is OffscreenCanvas|HTMLCanvasElement + static test(source: unknown): source is OffscreenCanvas | HTMLCanvasElement { const { OffscreenCanvas } = globalThis; diff --git a/packages/core/src/textures/resources/CubeResource.ts b/packages/core/src/textures/resources/CubeResource.ts index 19d1c56d5f8..dce34ca91c7 100644 --- a/packages/core/src/textures/resources/CubeResource.ts +++ b/packages/core/src/textures/resources/CubeResource.ts @@ -8,9 +8,7 @@ import type { BaseTexture } from '../BaseTexture'; import type { Renderer } from '../../Renderer'; import type { GLTexture } from '../GLTexture'; -/** - * Constructor options for CubeResource - */ +/** Constructor options for CubeResource */ export interface ICubeResourceOptions extends ISize { /** Whether to auto-load resources */ @@ -22,7 +20,6 @@ export interface ICubeResourceOptions extends ISize /** * Resource for a CubeTexture which contains six resources. - * * @memberof PIXI */ export class CubeResource extends AbstractMultiResource @@ -31,7 +28,6 @@ export class CubeResource extends AbstractMultiResource /** * In case BaseTextures are supplied, whether to use same resource or bind baseTexture itself. - * * @protected */ linkBaseTexture: boolean; @@ -46,7 +42,7 @@ export class CubeResource extends AbstractMultiResource * @param {number} [options.linkBaseTexture=true] - In case BaseTextures are supplied, * whether to copy them or use */ - constructor(source?: ArrayFixed, options?: ICubeResourceOptions) + constructor(source?: ArrayFixed, options?: ICubeResourceOptions) { const { width, height, autoLoad, linkBaseTexture } = options || {}; @@ -77,7 +73,6 @@ export class CubeResource extends AbstractMultiResource /** * Add binding. - * * @param baseTexture - parent base texture */ bind(baseTexture: BaseTexture): void @@ -134,7 +129,9 @@ export class CubeResource extends AbstractMultiResource /** * Upload the resource - * + * @param renderer + * @param _baseTexture + * @param glTexture * @returns {boolean} true is success */ upload(renderer: Renderer, _baseTexture: BaseTexture, glTexture: GLTexture): boolean @@ -145,7 +142,7 @@ export class CubeResource extends AbstractMultiResource { const side = this.items[i]; - if (dirty[i] < side.dirtyId) + if (dirty[i] < side.dirtyId || glTexture.dirtyId < _baseTexture.dirtyId) { if (side.valid && side.resource) { @@ -177,11 +174,10 @@ export class CubeResource extends AbstractMultiResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object - * @return {boolean} `true` if source is an array of 6 elements + * @returns {boolean} `true` if source is an array of 6 elements */ - static test(source: unknown): source is ArrayFixed + static test(source: unknown): source is ArrayFixed { return Array.isArray(source) && source.length === CubeResource.SIDES; } diff --git a/packages/core/src/textures/resources/DepthResource.ts b/packages/core/src/textures/resources/DepthResource.ts index 8b01c5381c0..68080be37b2 100644 --- a/packages/core/src/textures/resources/DepthResource.ts +++ b/packages/core/src/textures/resources/DepthResource.ts @@ -7,18 +7,16 @@ import type { GLTexture } from '../GLTexture'; /** * Resource type for DepthTexture. - * * @memberof PIXI */ export class DepthResource extends BufferResource { /** * Upload the texture to the GPU. - * * @param renderer - Upload to the renderer * @param baseTexture - Reference to parent texture * @param glTexture - glTexture - * @return - true is success + * @returns - true is success */ upload(renderer: Renderer, baseTexture: BaseTexture, glTexture: GLTexture): boolean { diff --git a/packages/core/src/textures/resources/ImageBitmapResource.ts b/packages/core/src/textures/resources/ImageBitmapResource.ts index 28840e70b23..d5054231555 100644 --- a/packages/core/src/textures/resources/ImageBitmapResource.ts +++ b/packages/core/src/textures/resources/ImageBitmapResource.ts @@ -2,7 +2,6 @@ import { BaseImageResource } from './BaseImageResource'; /** * Resource type for ImageBitmap. - * * @memberof PIXI */ export class ImageBitmapResource extends BaseImageResource @@ -18,12 +17,11 @@ export class ImageBitmapResource extends BaseImageResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object - * @return {boolean} `true` if source is an ImageBitmap + * @returns {boolean} `true` if source is an ImageBitmap */ static test(source: unknown): source is ImageBitmap { - return !!globalThis.createImageBitmap && source instanceof ImageBitmap; + return !!globalThis.createImageBitmap && typeof ImageBitmap !== 'undefined' && source instanceof ImageBitmap; } } diff --git a/packages/core/src/textures/resources/ImageResource.ts b/packages/core/src/textures/resources/ImageResource.ts index 8357a66cd14..7eb85399042 100644 --- a/packages/core/src/textures/resources/ImageResource.ts +++ b/packages/core/src/textures/resources/ImageResource.ts @@ -15,7 +15,7 @@ export interface IImageResourceOptions createBitmap?: boolean; /** Load image using cross origin. */ - crossorigin?: boolean|string; + crossorigin?: boolean | string; /** Premultiply image alpha in bitmap. */ alphaMode?: ALPHA_MODES; @@ -23,7 +23,6 @@ export interface IImageResourceOptions /** * Resource type for HTMLImageElement. - * * @memberof PIXI */ export class ImageResource extends BaseImageResource @@ -33,14 +32,12 @@ export class ImageResource extends BaseImageResource /** * If the image should be disposed after upload - * * @default false */ preserveBitmap: boolean; /** * If capable, convert the image using createImageBitmap API. - * * @default PIXI.settings.CREATE_IMAGE_BITMAP */ createBitmap: boolean; @@ -49,21 +46,18 @@ export class ImageResource extends BaseImageResource * Controls texture alphaMode field * Copies from options * Default is `null`, copies option from baseTexture - * * @readonly */ alphaMode: ALPHA_MODES; /** * The ImageBitmap element created for a {@code HTMLImageElement}. - * * @default null */ bitmap: ImageBitmap; /** * Promise when loading. - * * @default null */ private _load: Promise; @@ -80,7 +74,7 @@ export class ImageResource extends BaseImageResource * @param {boolean} [options.crossorigin=true] - Load image using cross origin * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.UNPACK] - Premultiply image alpha in bitmap */ - constructor(source: HTMLImageElement|string, options?: IImageResourceOptions) + constructor(source: HTMLImageElement | string, options?: IImageResourceOptions) { options = options || {}; @@ -111,8 +105,7 @@ export class ImageResource extends BaseImageResource this._process = null; this.preserveBitmap = false; - this.createBitmap = (options.createBitmap !== undefined - ? options.createBitmap : settings.CREATE_IMAGE_BITMAP) && !!globalThis.createImageBitmap; + this.createBitmap = (options.createBitmap ?? settings.CREATE_IMAGE_BITMAP) && !!globalThis.createImageBitmap; this.alphaMode = typeof options.alphaMode === 'number' ? options.alphaMode : null; this.bitmap = null; @@ -126,7 +119,6 @@ export class ImageResource extends BaseImageResource /** * Returns a promise when image will be loaded and processed. - * * @param createBitmap - whether process image into bitmap */ load(createBitmap?: boolean): Promise @@ -191,8 +183,7 @@ export class ImageResource extends BaseImageResource /** * Called when we need to convert image into BitmapImage. * Can be called multiple times, real promise is cached inside. - * - * @return - Cached promise to fill that bitmap + * @returns - Cached promise to fill that bitmap */ process(): Promise { @@ -238,7 +229,6 @@ export class ImageResource extends BaseImageResource /** * Upload the image resource to GPU. - * * @param renderer - Renderer to upload to * @param baseTexture - BaseTexture for this resource * @param glTexture - GLTexture to use @@ -321,11 +311,10 @@ export class ImageResource extends BaseImageResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object - * @return {boolean} `true` if source is string or HTMLImageElement + * @returns {boolean} `true` if source is string or HTMLImageElement */ - static test(source: unknown): source is string|HTMLImageElement + static test(source: unknown): source is string | HTMLImageElement { return typeof source === 'string' || source instanceof HTMLImageElement; } diff --git a/packages/core/src/textures/resources/Resource.ts b/packages/core/src/textures/resources/Resource.ts index 51b422f78cd..fc206c23669 100644 --- a/packages/core/src/textures/resources/Resource.ts +++ b/packages/core/src/textures/resources/Resource.ts @@ -8,14 +8,15 @@ import type { GLTexture } from '../GLTexture'; * Base resource class for textures that manages validation and uploading, depending on its type. * * Uploading of a base texture to the GPU is required. - * * @memberof PIXI */ export abstract class Resource { + /** The url of the resource */ + public src: string; + /** * If resource has been destroyed. - * * @readonly * @default false */ @@ -38,7 +39,6 @@ export abstract class Resource /** * Mini-runner for handling resize events * accepts 2 parameters: width, height - * * @member {Runner} * @private */ @@ -46,7 +46,6 @@ export abstract class Resource /** * Mini-runner for handling update events - * * @member {Runner} * @private */ @@ -55,7 +54,6 @@ export abstract class Resource /** * Handle internal errors, such as loading errors * accepts 1 param: error - * * @member {Runner} * @private */ @@ -80,7 +78,6 @@ export abstract class Resource /** * Bind to a parent BaseTexture - * * @param baseTexture - Parent texture */ bind(baseTexture: BaseTexture): void @@ -99,7 +96,6 @@ export abstract class Resource /** * Unbind to a parent BaseTexture - * * @param baseTexture - Parent texture */ unbind(baseTexture: BaseTexture): void @@ -111,7 +107,6 @@ export abstract class Resource /** * Trigger a resize event - * * @param width - X dimension * @param height - Y dimension */ @@ -127,7 +122,6 @@ export abstract class Resource /** * Has been validated - * * @readonly */ get valid(): boolean @@ -147,9 +141,8 @@ export abstract class Resource /** * This can be overridden to start preloading a resource * or do any other prepare step. - * * @protected - * @return Handle the validate event + * @returns Handle the validate event */ load(): Promise { @@ -158,7 +151,6 @@ export abstract class Resource /** * The width of the resource. - * * @readonly */ get width(): number @@ -168,7 +160,6 @@ export abstract class Resource /** * The height of the resource. - * * @readonly */ get height(): number @@ -178,7 +169,6 @@ export abstract class Resource /** * Uploads the texture or returns false if it cant for some reason. Override this. - * * @param renderer - yeah, renderer! * @param baseTexture - the texture * @param glTexture - texture instance for this webgl context @@ -188,10 +178,9 @@ export abstract class Resource /** * Set the style, optional to override - * - * @param renderer - yeah, renderer! - * @param baseTexture - the texture - * @param glTexture - texture instance for this webgl context + * @param _renderer - yeah, renderer! + * @param _baseTexture - the texture + * @param _glTexture - texture instance for this webgl context * @returns - `true` is success */ style(_renderer: Renderer, _baseTexture: BaseTexture, _glTexture: GLTexture): boolean @@ -227,9 +216,8 @@ export abstract class Resource /** * Abstract, used to auto-detect resource type. - * - * @param {*} source - The source object - * @param {string} extension - The extension of source, if set + * @param {*} _source - The source object + * @param {string} _extension - The extension of source, if set */ static test(_source: unknown, _extension?: string): boolean { diff --git a/packages/core/src/textures/resources/SVGResource.ts b/packages/core/src/textures/resources/SVGResource.ts index 7432530b57c..3a9d2a945bd 100644 --- a/packages/core/src/textures/resources/SVGResource.ts +++ b/packages/core/src/textures/resources/SVGResource.ts @@ -1,5 +1,6 @@ import { uid } from '@pixi/utils'; import { BaseImageResource } from './BaseImageResource'; +import { settings } from '@pixi/settings'; import type { ISize } from '@pixi/math'; @@ -10,11 +11,10 @@ export interface ISVGResourceOptions width?: number; height?: number; autoLoad?: boolean; - crossorigin?: boolean|string; + crossorigin?: boolean | string; } /** * Resource type for SVG elements and graphics. - * * @memberof PIXI */ export class SVGResource extends BaseImageResource @@ -38,7 +38,7 @@ export class SVGResource extends BaseImageResource private _load: Promise; /** Cross origin value to use */ - private _crossorigin?: boolean|string; + private _crossorigin?: boolean | string; /** * @param sourceBase64 - Base64 encoded SVG element or URL for SVG file. @@ -52,7 +52,7 @@ export class SVGResource extends BaseImageResource { options = options || {}; - super(document.createElement('canvas')); + super(settings.ADAPTER.createCanvas()); this._width = 0; this._height = 0; @@ -168,9 +168,8 @@ export class SVGResource extends BaseImageResource /** * Get size from an svg string using a regular expression. - * * @param svgString - a serialized svg element - * @return - image extension + * @returns - image extension */ static getSize(svgString?: string): ISize { @@ -196,10 +195,9 @@ export class SVGResource extends BaseImageResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object * @param {string} extension - The extension of source, if set - * @return {boolean} - If the source is a SVG source or data file + * @returns {boolean} - If the source is a SVG source or data file */ static test(source: unknown, extension?: string): boolean { @@ -213,7 +211,6 @@ export class SVGResource extends BaseImageResource /** * Regular expression for SVG XML document. - * * @example <?xml version="1.0" encoding="utf-8" ?><!-- image/svg --><svg * @readonly */ @@ -221,7 +218,6 @@ export class SVGResource extends BaseImageResource /** * Regular expression for SVG size. - * * @example <svg width="100" height="100"></svg> * @readonly */ diff --git a/packages/core/src/textures/resources/VideoResource.ts b/packages/core/src/textures/resources/VideoResource.ts index 705e2dd7fee..5c5e809fab7 100644 --- a/packages/core/src/textures/resources/VideoResource.ts +++ b/packages/core/src/textures/resources/VideoResource.ts @@ -8,7 +8,7 @@ export interface IVideoResourceOptions autoLoad?: boolean; autoPlay?: boolean; updateFPS?: number; - crossorigin?: boolean|string; + crossorigin?: boolean | string; } export interface IVideoResourceOptionsElement @@ -19,7 +19,6 @@ export interface IVideoResourceOptionsElement /** * Resource type for {@code HTMLVideoElement}. - * * @memberof PIXI */ export class VideoResource extends BaseImageResource @@ -29,14 +28,12 @@ export class VideoResource extends BaseImageResource /** * `true` to use PIXI.Ticker.shared to auto update the base texture. - * * @default true */ protected _autoUpdate: boolean; /** * `true` if the instance is currently connected to PIXI.Ticker.shared to auto update the base texture. - * * @default false */ protected _isConnectedToTicker: boolean; @@ -46,14 +43,12 @@ export class VideoResource extends BaseImageResource /** * When set to true will automatically play videos used by this texture once * they are loaded. If false, it will not modify the playing state. - * * @default true */ protected autoPlay: boolean; /** * Promise when loading. - * * @default null */ private _load: Promise; @@ -70,7 +65,9 @@ export class VideoResource extends BaseImageResource * Leave at 0 to update at every render. * @param {boolean} [options.crossorigin=true] - Load image using cross origin */ - constructor(source?: HTMLVideoElement|Array|string, options?: IVideoResourceOptions) + constructor( + source?: HTMLVideoElement | Array | string, options?: IVideoResourceOptions + ) { options = options || {}; @@ -142,8 +139,7 @@ export class VideoResource extends BaseImageResource /** * Trigger updating of the texture. - * - * @param deltaTime - time delta since last tick + * @param _deltaTime - time delta since last tick */ update(_deltaTime = 0): void { @@ -163,8 +159,7 @@ export class VideoResource extends BaseImageResource /** * Start preloading the video resource. - * - * @return {Promise} Handle the validate event + * @returns {Promise} Handle the validate event */ load(): Promise { @@ -212,7 +207,10 @@ export class VideoResource extends BaseImageResource return this._load; } - /** Handle video error events. */ + /** + * Handle video error events. + * @param event + */ private _onError(event: ErrorEvent): void { (this.source as HTMLVideoElement).removeEventListener('error', this._onError, true); @@ -221,8 +219,7 @@ export class VideoResource extends BaseImageResource /** * Returns true if the underlying source is playing. - * - * @return - True if playing. + * @returns - True if playing. */ private _isSourcePlaying(): boolean { @@ -233,8 +230,7 @@ export class VideoResource extends BaseImageResource /** * Returns true if the underlying source is ready for playing. - * - * @return - True if ready. + * @returns - True if ready. */ private _isSourceReady(): boolean { @@ -363,27 +359,24 @@ export class VideoResource extends BaseImageResource /** * Used to auto-detect the type of resource. - * * @param {*} source - The source object * @param {string} extension - The extension of source, if set - * @return {boolean} `true` if video source + * @returns {boolean} `true` if video source */ static test(source: unknown, extension?: string): source is HTMLVideoElement { return (globalThis.HTMLVideoElement && source instanceof HTMLVideoElement) - || VideoResource.TYPES.indexOf(extension) > -1; + || VideoResource.TYPES.includes(extension); } /** * List of common video file extensions supported by VideoResource. - * * @readonly */ static TYPES: Array = ['mp4', 'm4v', 'webm', 'ogg', 'ogv', 'h264', 'avi', 'mov']; /** * Map of video MIME types that can't be directly derived from file extensions. - * * @readonly */ static MIME_TYPES: Dict = { diff --git a/packages/core/src/textures/resources/autoDetectResource.ts b/packages/core/src/textures/resources/autoDetectResource.ts index dbf90a3bc3e..5a6c099a3d9 100644 --- a/packages/core/src/textures/resources/autoDetectResource.ts +++ b/packages/core/src/textures/resources/autoDetectResource.ts @@ -1,4 +1,4 @@ -import { Resource } from './Resource'; +import type { Resource } from './Resource'; import type { IImageResourceOptions } from './ImageResource'; import type { ISize } from '@pixi/math'; @@ -15,15 +15,14 @@ export type IResourcePluginOptions = { [key: string]: any }; * All allowable options for autoDetectResource */ export type IAutoDetectOptions = ISize - | ICubeResourceOptions - | IImageResourceOptions - | ISVGResourceOptions - | IVideoResourceOptions - | IResourcePluginOptions; +| ICubeResourceOptions +| IImageResourceOptions +| ISVGResourceOptions +| IVideoResourceOptions +| IResourcePluginOptions; /** * Shape of supported resource plugins - * * @memberof PIXI */ export interface IResourcePlugin @@ -52,7 +51,6 @@ export interface IResourcePlugin * } * // Install the new resource type * PIXI.INSTALLED.push(CustomResource); - * * @memberof PIXI * @type {Array} * @static @@ -88,7 +86,7 @@ export const INSTALLED: Array> = []; * @param {boolean} [options.autoPlay=true] - Video option to start playing video immediately * @param {number} [options.updateFPS=0] - Video option to update how many times a second the * texture should be updated from the video. Leave at 0 to update at every render - * @return {PIXI.Resource} The created resource. + * @returns {PIXI.Resource} The created resource. */ export function autoDetectResource(source: unknown, options?: RO): R { diff --git a/packages/core/src/textures/utils/mapTypeAndFormatToInternalFormat.ts b/packages/core/src/textures/utils/mapTypeAndFormatToInternalFormat.ts index dde0c3f7385..74577faf212 100644 --- a/packages/core/src/textures/utils/mapTypeAndFormatToInternalFormat.ts +++ b/packages/core/src/textures/utils/mapTypeAndFormatToInternalFormat.ts @@ -2,15 +2,14 @@ import { FORMATS, TYPES } from '@pixi/constants'; /** * Returns a lookup table that maps each type-format pair to a compatible internal format. - * * @memberof PIXI * @function mapTypeAndFormatToInternalFormat * @private * @param {WebGLRenderingContext} gl - The rendering context. - * @return {{ [type: number]: { [format: number]: number } }} Lookup table. + * @returns Lookup table. */ export function mapTypeAndFormatToInternalFormat(gl: WebGLRenderingContextBase): - { [type: number]: { [format: number]: number } } +{ [type: number]: { [format: number]: number } } { let table; diff --git a/packages/core/src/utils/Quad.ts b/packages/core/src/utils/Quad.ts index 1aa1de38435..e5f692931e7 100644 --- a/packages/core/src/utils/Quad.ts +++ b/packages/core/src/utils/Quad.ts @@ -2,7 +2,6 @@ import { Geometry } from '../geometry/Geometry'; /** * Helper class to create a quad - * * @memberof PIXI */ export class Quad extends Geometry diff --git a/packages/core/src/utils/QuadUv.ts b/packages/core/src/utils/QuadUv.ts index eb4ef0a745f..f55bcd58705 100644 --- a/packages/core/src/utils/QuadUv.ts +++ b/packages/core/src/utils/QuadUv.ts @@ -5,7 +5,6 @@ import type { Rectangle } from '@pixi/math'; /** * Helper class to create a quad with uvs like in v4 - * * @memberof PIXI */ export class QuadUv extends Geometry @@ -47,10 +46,9 @@ export class QuadUv extends Geometry /** * Maps two Rectangle to the quad. - * * @param targetTextureFrame - The first rectangle * @param destinationFrame - The second rectangle - * @return - Returns itself. + * @returns - Returns itself. */ map(targetTextureFrame: Rectangle, destinationFrame: Rectangle): this { @@ -91,7 +89,6 @@ export class QuadUv extends Geometry /** * Legacy upload method, just marks buffers dirty. - * * @returns - Returns itself. */ invalidate(): this diff --git a/packages/core/src/view/ViewSystem.ts b/packages/core/src/view/ViewSystem.ts new file mode 100644 index 00000000000..5592d9cb1d8 --- /dev/null +++ b/packages/core/src/view/ViewSystem.ts @@ -0,0 +1,141 @@ +import { Rectangle } from '@pixi/math'; +import { settings } from '@pixi/settings'; +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; +import type { IRenderer } from '../IRenderer'; +import type { ISystem } from '../system/ISystem'; + +/** + * Options passed to the ViewSystem + * @memberof PIXI + */ +export interface ViewOptions +{ + /** The width of the screen. */ + width: number + /** The height of the screen. */ + height: number + /** The canvas to use as a view, optional. */ + view?: HTMLCanvasElement; + /** Resizes renderer view in CSS pixels to allow for resolutions other than 1. */ + autoDensity?: boolean + /** The resolution / device pixel ratio of the renderer. */ + resolution?: number +} + +/** + * The view system manages the main canvas that is attached to the DOM. + * This main role is to deal with how the holding the view reference and dealing with how it is resized. + * @memberof PIXI + */ +export class ViewSystem implements ISystem +{ + /** @ignore */ + static extension: ExtensionMetadata = { + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + name: '_view', + }; + + private renderer: IRenderer; + + /** + * The resolution / device pixel ratio of the renderer. + * @member {number} + * @default PIXI.settings.RESOLUTION + */ + public resolution: number; + + /** + * Measurements of the screen. (0, 0, screenWidth, screenHeight). + * + * Its safe to use as filterArea or hitArea for the whole stage. + * @member {PIXI.Rectangle} + */ + public screen: Rectangle; + + /** + * The canvas element that everything is drawn to. + * @member {HTMLCanvasElement} + */ + public element: HTMLCanvasElement; + + /** + * Whether CSS dimensions of canvas view should be resized to screen dimensions automatically. + * @member {boolean} + */ + public autoDensity: boolean; + + constructor(renderer: IRenderer) + { + this.renderer = renderer; + } + + /** + * initiates the view system + * @param {PIXI.ViewOptions} options - the options for the view + */ + init(options: ViewOptions): void + { + this.screen = new Rectangle(0, 0, options.width, options.height); + + this.element = options.view || settings.ADAPTER.createCanvas(); + + this.resolution = options.resolution || settings.RESOLUTION; + + this.autoDensity = !!options.autoDensity; + } + + /** + * Resizes the screen and canvas to the specified dimensions. + * @param desiredScreenWidth - The new width of the screen. + * @param desiredScreenHeight - The new height of the screen. + */ + resizeView(desiredScreenWidth: number, desiredScreenHeight: number): void + { + this.element.width = Math.round(desiredScreenWidth * this.resolution); + this.element.height = Math.round(desiredScreenHeight * this.resolution); + + const screenWidth = this.element.width / this.resolution; + const screenHeight = this.element.height / this.resolution; + + this.screen.width = screenWidth; + this.screen.height = screenHeight; + + if (this.autoDensity) + { + this.element.style.width = `${screenWidth}px`; + this.element.style.height = `${screenHeight}px`; + } + + /** + * Fired after view has been resized. + * @event PIXI.Renderer#resize + * @param {number} screenWidth - The new width of the screen. + * @param {number} screenHeight - The new height of the screen. + */ + this.renderer.emit('resize', screenWidth, screenHeight); + this.renderer.runners.resize.emit(this.screen.width, this.screen.height); + } + + /** + * Destroys this System and optionally removes the canvas from the dom. + * @param {boolean} [removeView=false] - Whether to remove the canvas from the DOM. + */ + destroy(removeView: boolean): void + { + // ka boom! + if (removeView && this.element.parentNode) + { + this.element.parentNode.removeChild(this.element); + } + + this.renderer = null; + this.element = null; + this.screen = null; + } +} + +extensions.add(ViewSystem); diff --git a/packages/core/test/ArrayResource.tests.ts b/packages/core/test/ArrayResource.tests.ts index 9c8826ef65c..3ac4ef61c93 100644 --- a/packages/core/test/ArrayResource.tests.ts +++ b/packages/core/test/ArrayResource.tests.ts @@ -1,66 +1,67 @@ +import type { BaseTexture } from '@pixi/core'; import { ArrayResource, ImageResource } from '@pixi/core'; import { join } from 'path'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('ArrayResource', function () +describe('ArrayResource', () => { - before(function () + let basePath: string; + let imageUrl: string; + + beforeAll(() => { - this.basePath = join(__dirname, 'resources'); - this.imageUrl = join(this.basePath, 'slug.png'); + basePath = join(__dirname, 'resources'); + imageUrl = join(basePath, 'slug.png'); }); - it('should create new resource by length', function () + it('should create new resource by length', () => { const resource = new ArrayResource(5, { width: 100, height: 100 }); resource.destroy(); - expect(resource.destroyed).to.be.true; + expect(resource.destroyed).toBe(true); }); - it('should error on out of bound', function () + it('should error on out of bound', () => { const resource = new ArrayResource(5, { width: 100, height: 100 }); - const image = new ImageResource(this.imageUrl); + const image = new ImageResource(imageUrl); - expect(() => resource.addResourceAt(image, 10)).to.throw(Error, /out of bounds/); + expect(() => resource.addResourceAt(image, 10)).toThrowWithMessage(Error, 'Index 10 is out of bounds'); resource.destroy(); }); - it('should load array of URL resources', function () + it('should load array of URL resources', () => { const images = [ - this.imageUrl, - this.imageUrl, - this.imageUrl, - this.imageUrl, + imageUrl, + imageUrl, + imageUrl, + imageUrl, ]; const resource = new ArrayResource(images, { width: 100, height: 100, - autoLoad: false, }); const baseTexture = { - setRealSize: sinon.stub(), - update: sinon.stub(), - }; + setRealSize: jest.fn(), + update: jest.fn(), + } as unknown as BaseTexture; resource.bind(baseTexture); return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(baseTexture.setRealSize.calledOnce).to.be.true; + expect(res).toEqual(resource); + expect(baseTexture.setRealSize).toBeCalledTimes(1); for (let i = 0; i < images.length; i++) { const item = resource.items[i].resource; - expect(item.valid).to.be.true; - expect(item.width).to.equal(100); - expect(item.height).to.equal(100); + expect(item.valid).toBe(true); + expect(item.width).toEqual(100); + expect(item.height).toEqual(100); } resource.unbind(baseTexture); resource.destroy(); diff --git a/packages/core/test/BaseTexture.tests.ts b/packages/core/test/BaseTexture.tests.ts index bafee3bf399..ba400675656 100644 --- a/packages/core/test/BaseTexture.tests.ts +++ b/packages/core/test/BaseTexture.tests.ts @@ -1,7 +1,6 @@ import { BaseTextureCache, TextureCache } from '@pixi/utils'; import { BaseTexture, Texture, RenderTexture, ImageResource, SVGResource, VideoResource } from '@pixi/core'; import { settings } from '@pixi/settings'; -import { expect } from 'chai'; const URL = 'foo.png'; const NAME = 'foo'; @@ -18,105 +17,93 @@ function cleanCache() delete TextureCache[NAME2]; } -describe('BaseTexture', function () +describe('BaseTexture', () => { - /* - describe('updateImageType', function () + interface PixiCanvas extends HTMLCanvasElement { - it('should allow no extension', function () - { - cleanCache(); - - const baseTexture = new BaseTexture(); - - baseTexture.imageUrl = 'http://some.domain.org/100/100'; - baseTexture._updateImageType(); - - expect(baseTexture.imageType).to.be.equals('png'); - }); - }); - */ + _pixiId: string; + } - it('should handle invalid image URL for textures', function (done) + it('should handle invalid image URL for textures', (done) => { cleanCache(); const invalidFile = 'missing-image.png'; const baseTexture = BaseTexture.from(invalidFile); - baseTexture.once('error', function (baseTexture, event) + baseTexture.once('error', (baseTexture, event) => { - expect(baseTexture.resource).to.be.instanceof(ImageResource); - expect(baseTexture.resource.url).contains(invalidFile); - expect(event.type).to.equal('error'); + expect(baseTexture.resource).toBeInstanceOf(ImageResource); + expect(baseTexture.resource.url).toInclude(invalidFile); + expect(event.type).toEqual('error'); baseTexture.destroy(); done(); }); }); - it('should handle invalid svg URL for textures', function (done) + it('should handle invalid svg URL for textures', (done) => { cleanCache(); const invalidFile = 'missing-image.svg'; const baseTexture = BaseTexture.from(invalidFile); - baseTexture.once('error', function (baseTexture, event) + baseTexture.once('error', (baseTexture, event) => { - expect(baseTexture.resource).to.be.instanceof(SVGResource); - expect(baseTexture.resource.svg).contains(invalidFile); - expect(event.type).to.equal('error'); + expect(baseTexture.resource).toBeInstanceOf(SVGResource); + expect(baseTexture.resource.svg).toInclude(invalidFile); + expect(event.type).toEqual('error'); baseTexture.destroy(); done(); }); }); - it('should handle invalid video URL for textures', function (done) + it('should handle invalid video URL for textures', (done) => { cleanCache(); const invalidFile = 'missing-image.mp4'; const baseTexture = BaseTexture.from(invalidFile); - baseTexture.once('error', function (baseTexture, event) + baseTexture.once('error', (baseTexture, event) => { - expect(baseTexture.resource).to.be.instanceof(VideoResource); - expect(baseTexture.resource.source.firstChild.src).contains(invalidFile); - expect(event.type).to.equal('error'); + expect(baseTexture.resource).toBeInstanceOf(VideoResource); + expect(baseTexture.resource.source.firstChild.src).toInclude(invalidFile); + expect(event.type).toEqual('error'); baseTexture.destroy(); done(); }); }); - it('should use pixiIdPrefix correctly', function () + it('should use pixiIdPrefix correctly', () => { cleanCache(); - const canvas = document.createElement('canvas'); + const canvas = document.createElement('canvas') as PixiCanvas; const baseTexture = BaseTexture.from(canvas, { pixiIdPrefix: 'unittest' }); const _pixiId = canvas._pixiId; - expect(_pixiId.indexOf('unittest_')).to.equal(0); - expect(baseTexture.textureCacheIds.indexOf(_pixiId)).to.equal(0); - expect(BaseTextureCache[_pixiId]).to.equal(baseTexture); + expect(_pixiId.indexOf('unittest_')).toEqual(0); + expect(baseTexture.textureCacheIds.indexOf(_pixiId)).toEqual(0); + expect(BaseTextureCache[_pixiId]).toEqual(baseTexture); }); - it('should remove Canvas BaseTexture from cache on destroy', function () + it('should remove Canvas BaseTexture from cache on destroy', () => { cleanCache(); - const canvas = document.createElement('canvas'); + const canvas = document.createElement('canvas') as PixiCanvas; const baseTexture = BaseTexture.from(canvas); const _pixiId = canvas._pixiId; - expect(baseTexture.textureCacheIds.indexOf(_pixiId)).to.equal(0); - expect(BaseTextureCache[_pixiId]).to.equal(baseTexture); + expect(baseTexture.textureCacheIds.indexOf(_pixiId)).toEqual(0); + expect(BaseTextureCache[_pixiId]).toEqual(baseTexture); baseTexture.destroy(); - expect(baseTexture.textureCacheIds).to.equal(null); - expect(BaseTextureCache[_pixiId]).to.equal(undefined); + expect(baseTexture.textureCacheIds).toEqual(null); + expect(BaseTextureCache[_pixiId]).toEqual(undefined); }); - it('should remove Image BaseTexture from cache on destroy', function (done) + it('should remove Image BaseTexture from cache on destroy', (done) => { cleanCache(); @@ -127,19 +114,19 @@ describe('BaseTexture', function () Texture.fromLoader(image, URL, NAME).then((texture) => { - expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.baseTexture.textureCacheIds.indexOf(URL)).to.equal(1); - expect(BaseTextureCache[NAME]).to.equal(texture.baseTexture); + expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.baseTexture.textureCacheIds.indexOf(URL)).toEqual(1); + expect(BaseTextureCache[NAME]).toEqual(texture.baseTexture); texture.destroy(true); - expect(texture.baseTexture).to.equal(null); - expect(BaseTextureCache[NAME]).to.equal(undefined); - expect(BaseTextureCache[URL]).to.equal(undefined); + expect(texture.baseTexture).toEqual(null); + expect(BaseTextureCache[NAME]).toEqual(undefined); + expect(BaseTextureCache[URL]).toEqual(undefined); done(); }); }); - it('should remove BaseTexture from entire cache using removeFromCache (by BaseTexture instance)', function () + it('should remove BaseTexture from entire cache using removeFromCache (by BaseTexture instance)', () => { cleanCache(); @@ -147,18 +134,18 @@ describe('BaseTexture', function () BaseTexture.addToCache(baseTexture, NAME); BaseTexture.addToCache(baseTexture, NAME2); - expect(baseTexture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(baseTexture.textureCacheIds.indexOf(NAME2)).to.equal(1); - expect(BaseTextureCache[NAME]).to.equal(baseTexture); - expect(BaseTextureCache[NAME2]).to.equal(baseTexture); + expect(baseTexture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(baseTexture.textureCacheIds.indexOf(NAME2)).toEqual(1); + expect(BaseTextureCache[NAME]).toEqual(baseTexture); + expect(BaseTextureCache[NAME2]).toEqual(baseTexture); BaseTexture.removeFromCache(baseTexture); - expect(baseTexture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(baseTexture.textureCacheIds.indexOf(NAME2)).to.equal(-1); - expect(BaseTextureCache[NAME]).to.equal(undefined); - expect(BaseTextureCache[NAME2]).to.equal(undefined); + expect(baseTexture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(baseTexture.textureCacheIds.indexOf(NAME2)).toEqual(-1); + expect(BaseTextureCache[NAME]).toEqual(undefined); + expect(BaseTextureCache[NAME2]).toEqual(undefined); }); - it('should remove BaseTexture from single cache entry using removeFromCache (by id)', function () + it('should remove BaseTexture from single cache entry using removeFromCache (by id)', () => { cleanCache(); @@ -166,18 +153,18 @@ describe('BaseTexture', function () BaseTexture.addToCache(baseTexture, NAME); BaseTexture.addToCache(baseTexture, NAME2); - expect(baseTexture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(baseTexture.textureCacheIds.indexOf(NAME2)).to.equal(1); - expect(BaseTextureCache[NAME]).to.equal(baseTexture); - expect(BaseTextureCache[NAME2]).to.equal(baseTexture); + expect(baseTexture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(baseTexture.textureCacheIds.indexOf(NAME2)).toEqual(1); + expect(BaseTextureCache[NAME]).toEqual(baseTexture); + expect(BaseTextureCache[NAME2]).toEqual(baseTexture); BaseTexture.removeFromCache(NAME); - expect(baseTexture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(baseTexture.textureCacheIds.indexOf(NAME2)).to.equal(0); - expect(BaseTextureCache[NAME]).to.equal(undefined); - expect(BaseTextureCache[NAME2]).to.equal(baseTexture); + expect(baseTexture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(baseTexture.textureCacheIds.indexOf(NAME2)).toEqual(0); + expect(BaseTextureCache[NAME]).toEqual(undefined); + expect(BaseTextureCache[NAME2]).toEqual(baseTexture); }); - it('should not throw an error destroying a destroyed BaseTexture', function () + it('should not throw an error destroying a destroyed BaseTexture', () => { const baseTexture = new BaseTexture(); @@ -185,7 +172,7 @@ describe('BaseTexture', function () baseTexture.destroy(); }); - it('should update width and height', function () + it('should update width and height', () => { const canvas = document.createElement('canvas'); @@ -194,13 +181,13 @@ describe('BaseTexture', function () const baseTexture = BaseTexture.from(canvas); - expect(baseTexture.width).to.equal(canvas.width); - expect(baseTexture.height).to.equal(canvas.height); + expect(baseTexture.width).toEqual(canvas.width); + expect(baseTexture.height).toEqual(canvas.height); baseTexture.destroy(); }); - it('should set source.crossOrigin to anonymous if explicitly set', function () + it('should set source.crossOrigin to anonymous if explicitly set', () => { cleanCache(); @@ -209,14 +196,15 @@ describe('BaseTexture', function () }); const baseTexture = new BaseTexture(imageResource); + const source = (baseTexture.resource as ImageResource).source as HTMLImageElement; - expect(baseTexture.resource.source.crossOrigin).to.equal('anonymous'); + expect(source.crossOrigin).toEqual('anonymous'); baseTexture.destroy(); imageResource.destroy(); }); - it('should not destroy externally created resources', function () + it('should not destroy externally created resources', () => { cleanCache(); @@ -225,15 +213,15 @@ describe('BaseTexture', function () baseTexture.destroy(); - expect(baseTexture.destroyed).to.be.true; - expect(imageResource.destroyed).to.be.false; + expect(baseTexture.destroyed).toBe(true); + expect(imageResource.destroyed).toBe(false); imageResource.destroy(); - expect(imageResource.destroyed).to.be.true; + expect(imageResource.destroyed).toBe(true); }); - it('should destroy internally created resources', function () + it('should destroy internally created resources', () => { cleanCache(); @@ -242,26 +230,26 @@ describe('BaseTexture', function () baseTexture.destroy(); - expect(resource.destroyed).to.be.true; - expect(baseTexture.destroyed).to.be.true; + expect(resource.destroyed).toBe(true); + expect(baseTexture.destroyed).toBe(true); }); - it('should show correct width/height after setResolution', function () + it('should show correct width/height after setResolution', () => { const texture = RenderTexture.create({ width: 15, height: 15 }); texture.setResolution(0.9); - expect(texture.baseTexture.realWidth).to.equal(15); - expect(texture.baseTexture.realHeight).to.equal(15); + expect(texture.baseTexture.realWidth).toEqual(15); + expect(texture.baseTexture.realHeight).toEqual(15); }); - it('should throw and error in strict from mode', function () + it('should throw and error in strict from mode', () => { const id = 'baz'; - expect(() => BaseTexture.from(id, {}, true)).to.throw(`The cacheId "${id}" does not exist in BaseTextureCache.`); + expect(() => BaseTexture.from(id, {}, true)).toThrowError(`The cacheId "${id}" does not exist in BaseTextureCache.`); settings.STRICT_TEXTURE_CACHE = true; - expect(() => BaseTexture.from(id)).to.throw(`The cacheId "${id}" does not exist in BaseTextureCache.`); + expect(() => BaseTexture.from(id)).toThrowError(`The cacheId "${id}" does not exist in BaseTextureCache.`); settings.STRICT_TEXTURE_CACHE = false; }); }); diff --git a/packages/core/test/BatchRenderer.tests.ts b/packages/core/test/BatchRenderer.tests.ts index 30b125c04c9..e472596e3f7 100644 --- a/packages/core/test/BatchRenderer.tests.ts +++ b/packages/core/test/BatchRenderer.tests.ts @@ -1,14 +1,13 @@ +import type { IBatchableElement } from '@pixi/core'; import { Renderer, BatchRenderer, CanvasResource, Texture, BaseTexture } from '@pixi/core'; import { skipHello } from '@pixi/utils'; import { BLEND_MODES } from '@pixi/constants'; -import sinon from 'sinon'; -import { expect } from 'chai'; skipHello(); -describe('BatchRenderer', function () +describe('BatchRenderer', () => { - function createTexture(w, h) + function createTexture(w: number, h: number) { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); @@ -35,13 +34,13 @@ describe('BatchRenderer', function () const tint2 = 0xffff00; const tint3 = 0x00ffff; - it('should pass the batching test', function () + it('should pass the batching test', () => { const renderer = new Renderer({ width: 1, height: 1 }); const batchRenderer = new BatchRenderer(renderer); - const drawCalls = []; + const drawCalls = [] as number[]; - renderer.gl.drawElements = (type, size, indexType, start) => + renderer.gl.drawElements = (_type, size, _indexType, start) => { drawCalls.push(start, size); }; @@ -58,8 +57,8 @@ describe('BatchRenderer', function () _tintRGB: tint2, worldAlpha: 1.0, _texture: new Texture(tex1), blendMode: 0 }, { uvs, vertexData, indices, _tintRGB: tint3, worldAlpha: 1.0, _texture: new Texture(tex2), blendMode: 0 }, { uvs, vertexData, indices, _tintRGB: tint1, worldAlpha: 0.5, _texture: new Texture(tex4), blendMode: 0 }, - ]; - const nullArray = [null, null, null, null, null, null, null, null]; + ] as unknown as IBatchableElement[]; + const nullArray = [null, null, null, null, null, null, null, null] as null[]; try { @@ -68,17 +67,17 @@ describe('BatchRenderer', function () batchRenderer.MAX_TEXTURES = 2; batchRenderer.start(); elements.forEach((element) => batchRenderer.render(element)); - expect(batchRenderer._bufferedElements.length).to.equal(8); - expect(batchRenderer._bufferedTextures.length).to.equal(8); + expect(batchRenderer['_bufferedElements'].length).toEqual(8); + expect(batchRenderer['_bufferedTextures'].length).toEqual(8); batchRenderer.flush(); - expect(batchRenderer._bufferedElements).to.eql(nullArray); - expect(batchRenderer._bufferedTextures).to.eql(nullArray); + expect(batchRenderer['_bufferedElements']).toEqual(nullArray); + expect(batchRenderer['_bufferedTextures']).toEqual(nullArray); - const attrCount = batchRenderer._aIndex; + const attrCount = batchRenderer['_aIndex']; // first number is start * 2, second is size - expect(drawCalls).to.eql([0, 18, 36, 6, 48, 11, 70, 12]); - expect(attrCount).to.equal(198); + expect(drawCalls).toEqual([0, 18, 36, 6, 48, 11, 70, 12]); + expect(attrCount).toEqual(198); // eslint-disable-next-line no-console const attr = [0x0, 0x0, 0x0, 0x0, 0xffffffff, 0x0, @@ -120,14 +119,14 @@ describe('BatchRenderer', function () 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 25, 27, 28, 29, 30, 31, 29, 31, 32, ]; - const resultAttr = []; - const resultInd = []; + const resultAttr: number[] = []; + const resultInd: number[] = []; - batchRenderer._attributeBuffer.uint32View.slice(0, 198).forEach((x) => { resultAttr.push(x); }); - batchRenderer._indexBuffer.slice(0, 47).forEach((x) => { resultInd.push(x); }); + batchRenderer['_attributeBuffer'].uint32View.slice(0, 198).forEach((x) => { resultAttr.push(x); }); + batchRenderer['_indexBuffer'].slice(0, 47).forEach((x) => { resultInd.push(x); }); - expect(resultAttr).to.eql(attr); - expect(resultInd).to.eql(ind); + expect(resultAttr).toEqual(attr); + expect(resultInd).toEqual(ind); } finally { @@ -136,7 +135,7 @@ describe('BatchRenderer', function () } }); - it('should ask StateSystem to call gl.disable(gl.BLEND) if sprite has BLEND_MODES.NONE', function () + it('should ask StateSystem to call gl.disable(gl.BLEND) if sprite has BLEND_MODES.NONE', () => { const renderer = new Renderer({ width: 1, height: 1 }); const batchRenderer = new BatchRenderer(renderer); @@ -147,7 +146,7 @@ describe('BatchRenderer', function () blendMode: BLEND_MODES.NONE }, { uvs, vertexData, indices, _tintRGB: tint1, worldAlpha: 0.5, _texture: new Texture(tex1), blendMode: BLEND_MODES.NORMAL }, - ]; + ] as unknown as IBatchableElement[]; try { @@ -156,16 +155,16 @@ describe('BatchRenderer', function () batchRenderer.MAX_TEXTURES = 2; batchRenderer.start(); - const glEnable = sinon.spy(gl, 'enable'); - const glDisable = sinon.spy(gl, 'disable'); + const glEnable = jest.spyOn(gl, 'enable'); + const glDisable = jest.spyOn(gl, 'disable'); elements.forEach((element) => batchRenderer.render(element)); batchRenderer.flush(); - expect(glDisable.calledOnce).to.be.true; - expect(glDisable.args[0][0]).to.equal(gl.BLEND); - expect(glEnable.calledOnce).to.be.true; - expect(glEnable.args[0][0]).to.equal(gl.BLEND); + expect(glDisable).toBeCalledTimes(1); + expect(glDisable).toBeCalledWith(gl.BLEND); + expect(glEnable).toBeCalledTimes(1); + expect(glEnable).toBeCalledWith(gl.BLEND); } finally { diff --git a/packages/core/test/CanvasResource.tests.ts b/packages/core/test/CanvasResource.tests.ts index ef64620c17c..47ce232855f 100644 --- a/packages/core/test/CanvasResource.tests.ts +++ b/packages/core/test/CanvasResource.tests.ts @@ -1,23 +1,21 @@ import { CanvasResource, BaseTexture } from '@pixi/core'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('CanvasResource', function () +describe('CanvasResource', () => { - it('should create new dimension-less resource', function () + it('should create new dimension-less resource', () => { const canvas = document.createElement('canvas'); const resource = new CanvasResource(canvas); - expect(resource.width).to.equal(canvas.width); - expect(resource.height).to.equal(canvas.height); - expect(resource.valid).to.be.true; + expect(resource.width).toEqual(canvas.width); + expect(resource.height).toEqual(canvas.height); + expect(resource.valid).toBe(true); resource.destroy(); }); - it('should create new valid resource', function () + it('should create new valid resource', () => { const canvas = document.createElement('canvas'); @@ -26,46 +24,46 @@ describe('CanvasResource', function () const resource = new CanvasResource(canvas); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(200); - expect(resource.valid).to.be.true; + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(200); + expect(resource.valid).toBe(true); resource.destroy(); }); - it('should fire resize event on bind', function () + it('should fire resize event on bind', () => { const canvas = document.createElement('canvas'); const resource = new CanvasResource(canvas); - const baseTexture = { setRealSize: sinon.stub() }; + const baseTexture = { setRealSize: jest.fn() }; - resource.bind(baseTexture); + resource.bind(baseTexture as unknown as BaseTexture); - expect(baseTexture.setRealSize.calledOnce).to.be.true; + expect(baseTexture.setRealSize).toBeCalledTimes(1); - resource.unbind(baseTexture); + resource.unbind(baseTexture as unknown as BaseTexture); resource.destroy(); }); - it('should fire manual update event', function () + it('should fire manual update event', () => { const canvas = document.createElement('canvas'); const resource = new CanvasResource(canvas); - const baseTexture = { update: sinon.stub() }; + const baseTexture = { update: jest.fn() }; - resource.bind(baseTexture); + resource.bind(baseTexture as unknown as BaseTexture); - expect(baseTexture.update.called).to.be.false; + expect(baseTexture.update).not.toHaveBeenCalled(); resource.update(); - expect(baseTexture.update.calledOnce).to.be.true; + expect(baseTexture.update).toBeCalledTimes(1); - resource.unbind(baseTexture); + resource.unbind(baseTexture as unknown as BaseTexture); resource.destroy(); }); - it('should change BaseTexture size on update', function () + it('should change BaseTexture size on update', () => { const canvas = document.createElement('canvas'); @@ -75,13 +73,13 @@ describe('CanvasResource', function () const resource = new CanvasResource(canvas); const baseTexture = new BaseTexture(resource); - expect(baseTexture.width).to.equal(50); + expect(baseTexture.width).toEqual(50); canvas.width = 100; resource.update(); - expect(baseTexture.width).to.equal(100); + expect(baseTexture.width).toEqual(100); canvas.height = 70; resource.update(); - expect(baseTexture.height).to.equal(70); + expect(baseTexture.height).toEqual(70); resource.destroy(); }); }); diff --git a/packages/core/test/CubeResource.tests.ts b/packages/core/test/CubeResource.tests.ts index 842622c9e65..b0384873048 100644 --- a/packages/core/test/CubeResource.tests.ts +++ b/packages/core/test/CubeResource.tests.ts @@ -1,27 +1,29 @@ import { CubeResource, BaseTexture } from '@pixi/core'; import path from 'path'; -import { expect } from 'chai'; -describe('CubeResource', function () +describe('CubeResource', () => { - before(function () + let baseTexUrl: string; + + beforeAll(() => { - this.baseTexUrl = path.resolve(__dirname, 'resources', 'slug.png'); + baseTexUrl = path.resolve(__dirname, 'resources', 'slug.png'); }); - it('should create invalid length resource', function () + it('should create invalid length resource', () => { expect(() => { + // @ts-expect-error - using an invalid length // eslint-disable-next-line no-new new CubeResource([null, null, null, null, null, null, null, null]); - }).to.throw(Error, /invalid length/i); + }).toThrowWithMessage(Error, 'Invalid length. Got 8, expected 6'); }); - it('should be created through BaseTexture.from()', function () + it('should be created through BaseTexture.from()', () => { - const path1 = this.baseTexUrl; + const path1 = baseTexUrl; const baseTex = BaseTexture.from([path1, path1, path1, path1, path1, path1]); - expect(baseTex.resource).to.be.instanceof(CubeResource); + expect(baseTex.resource).toBeInstanceOf(CubeResource); }); }); diff --git a/packages/core/test/FilterSystem.tests.ts b/packages/core/test/FilterSystem.tests.ts index f065f976277..2acb853fa45 100644 --- a/packages/core/test/FilterSystem.tests.ts +++ b/packages/core/test/FilterSystem.tests.ts @@ -1,12 +1,11 @@ -import { CLEAR_MODES, BLEND_MODES } from '@pixi/constants'; -import { Rectangle, Matrix } from '@pixi/math'; -import { Renderer, Filter } from '@pixi/core'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { CLEAR_MODES } from '@pixi/constants'; +import type { IFilterTarget } from '@pixi/core'; +import { Filter, Renderer } from '@pixi/core'; +import { Matrix, Rectangle } from '@pixi/math'; -describe('FilterSystem', function () +describe('FilterSystem', () => { - function onePixelObject(worldTransform, size = 1) + function onePixelObject(worldTransform?: Matrix, size = 1) { const mat = worldTransform || Matrix.IDENTITY; @@ -15,27 +14,29 @@ describe('FilterSystem', function () worldTransform: mat, getBounds() { return new Rectangle(mat.tx, mat.ty, size, size); }, render() { /* nothing*/ }, - }; + } as unknown as IFilterTarget; } - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should support clearMode', function () + it('should support clearMode', () => { const innerFilter = new Filter(); const filter = new Filter(); - const clearSpy = sinon.spy(this.renderer.framebuffer, 'clear'); + const clearSpy = jest.spyOn(renderer.framebuffer, 'clear'); const obj = onePixelObject(); - const filterSystem = this.renderer.filter; + const filterSystem = renderer.filter; innerFilter.state.blend = false; @@ -52,14 +53,14 @@ describe('FilterSystem', function () let prevCalls = 0; - function render(clearMode, forceClear) + function render(clearMode: CLEAR_MODES, forceClear: boolean) { clearModeValue = clearMode; filterSystem.forceClear = forceClear; filterSystem.push(obj, [filter]); filterSystem.pop(); - const val = clearSpy.callCount; + const val = clearSpy.mock.calls.length; const clears = val - prevCalls - 1; prevCalls = val; @@ -67,29 +68,28 @@ describe('FilterSystem', function () return clears; } - expect(render(CLEAR_MODES.BLEND, false)).to.equal(0); - expect(render(CLEAR_MODES.BLEND, true)).to.equal(0); - expect(render(CLEAR_MODES.CLEAR, false)).to.equal(1); - expect(render(CLEAR_MODES.CLEAR, true)).to.equal(1); - expect(render(CLEAR_MODES.AUTO, false)).to.equal(0); - expect(render(CLEAR_MODES.AUTO, true)).to.equal(1); + expect(render(CLEAR_MODES.BLEND, false)).toEqual(0); + expect(render(CLEAR_MODES.BLEND, true)).toEqual(0); + expect(render(CLEAR_MODES.CLEAR, false)).toEqual(1); + expect(render(CLEAR_MODES.CLEAR, true)).toEqual(1); + expect(render(CLEAR_MODES.AUTO, false)).toEqual(0); + expect(render(CLEAR_MODES.AUTO, true)).toEqual(1); // check that there are two temp textures of same size const keys = Object.keys(filterSystem.texturePool.texturePool); - expect(keys.sort()).to.deep.eq(['65537']); - expect(filterSystem.texturePool.texturePool[65537].length).to.equal(2); + expect(keys.sort()).toEqual(['65537']); + expect(filterSystem.texturePool.texturePool[65537].length).toEqual(2); }); - function rectToString(rect) + function rectToString(rect: Rectangle) { return `(${rect.x}, ${rect.y}, ${rect.width}, ${rect.height})`; } - it('should account autoFit for global projection transform and rounding', function () + it('should account autoFit for global projection transform and rounding', () => { const obj = onePixelObject(new Matrix().translate(20, 10), 10); - const { renderer } = this; const src = new Rectangle(9, 10, 100, 100); const dst = new Rectangle(0, 0, 50, 50); const trans = new Matrix().translate(-14, -5); @@ -102,36 +102,35 @@ describe('FilterSystem', function () renderer.filter.push(obj, filters); - expect(renderer.projection.transform).to.be.null; + expect(renderer.projection.transform).toBeNull(); const newSrc = renderer.projection.sourceFrame; const newDst = renderer.projection.destinationFrame; // coords are cut to left-top corner of src, moved by inverse of transform - expect(newSrc.x).equal(23); - expect(newSrc.y).equal(15); + expect(newSrc.x).toEqual(23); + expect(newSrc.y).toEqual(15); // 20-14 = 6, but left pixel start at 9, so we cut 3 pixels, making width=10-3=7, // but round it to 8 because we scale it down 2 times in src->dst - expect(newSrc.width).equal(8); + expect(newSrc.width).toEqual(8); // cut 5 pixels from height, 10-5=5, rounded up to 6 to match resulting pixel grid - expect(newSrc.height).equal(6); + expect(newSrc.height).toEqual(6); // destination has the same size - expect(newDst.width).equal(8); - expect(newDst.height).equal(6); + expect(newDst.width).toEqual(8); + expect(newDst.height).toEqual(6); renderer.filter.pop(); - expect(renderer.projection.transform).to.equal(trans); - expect(rectToString(renderer.projection.sourceFrame)).equal(rectToString(src)); - expect(rectToString(renderer.projection.destinationFrame)).equal(rectToString(dst)); + expect(renderer.projection.transform).toEqual(trans); + expect(rectToString(renderer.projection.sourceFrame)).toEqual(rectToString(src)); + expect(rectToString(renderer.projection.destinationFrame)).toEqual(rectToString(dst)); renderer.projection.transform = null; }); - it('should round the source frame in screen space even when rotated by 90°', function () + it('should round the source frame in screen space even when rotated by 90°', () => { const obj = { getBounds() { return new Rectangle(0.1, 0.1, 100, 100); }, render() { /* Mock */ }, - }; - const { renderer } = this; + } as unknown as IFilterTarget; const src = new Rectangle(0, 0, 101, 101); const dst = new Rectangle(0, 0, 50, 50); const transform = new Matrix() @@ -147,12 +146,11 @@ describe('FilterSystem', function () renderer.filter.push(obj, filters); const newSrc = renderer.projection.sourceFrame; - const newDst = renderer.projection.destinationFrame; // Coords are shifted by 2x (0.1, 0.1) - expect(newSrc.x).to.be.closeTo(-0.9, 1e-5); - expect(newSrc.y).to.be.closeTo(-0.9, 1e-5); - expect(newSrc.width).to.closeTo(101, 1e-5); - expect(newSrc.height).to.closeTo(101, 1e-5); + expect(newSrc.x).toBeCloseTo(-0.9, 1e-5); + expect(newSrc.y).toBeCloseTo(-0.9, 1e-5); + expect(newSrc.width).toBeCloseTo(101, 1e-5); + expect(newSrc.height).toBeCloseTo(101, 1e-5); }); }); diff --git a/packages/core/test/FramebufferSystem.tests.ts b/packages/core/test/FramebufferSystem.tests.ts index 0d2cc8e9671..6ebd555d191 100644 --- a/packages/core/test/FramebufferSystem.tests.ts +++ b/packages/core/test/FramebufferSystem.tests.ts @@ -1,78 +1,79 @@ import { Renderer, Framebuffer } from '@pixi/core'; import { MSAA_QUALITY } from '@pixi/constants'; import { Rectangle } from '@pixi/math'; -import { expect } from 'chai'; -describe('FramebufferSystem', function () +describe('FramebufferSystem', () => { - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should choose correct AA samples based on samples array', function () + it('should choose correct AA samples based on samples array', () => { - const { framebuffer } = this.renderer; + const { framebuffer } = renderer; // chrome, general - framebuffer.msaaSamples = [8, 4, 1]; - expect(framebuffer.detectSamples(1)).to.equal(0); - expect(framebuffer.detectSamples(4)).to.equal(4); - expect(framebuffer.detectSamples(8)).to.equal(8); + framebuffer['msaaSamples'] = [8, 4, 1]; + expect(framebuffer['detectSamples'](1)).toEqual(0); + expect(framebuffer['detectSamples'](4)).toEqual(4); + expect(framebuffer['detectSamples'](8)).toEqual(8); // some mobile devices - framebuffer.msaaSamples = [4, 1]; - expect(framebuffer.detectSamples(8)).to.equal(4); + framebuffer['msaaSamples'] = [4, 1]; + expect(framebuffer['detectSamples'](8)).toEqual(4); // firefox on mac - framebuffer.msaaSamples = [8, 4]; - expect(framebuffer.detectSamples(1)).to.equal(0); + framebuffer['msaaSamples'] = [8, 4]; + expect(framebuffer['detectSamples'](1)).toEqual(0); // no MSAA - framebuffer.msaaSamples = null; - expect(framebuffer.detectSamples(8)).to.equal(0); + framebuffer['msaaSamples'] = null; + expect(framebuffer['detectSamples'](8)).toEqual(0); }); - it('should render to mip levels', function () + it('should render to mip levels', () => { - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); - this.renderer.framebuffer.bind(framebuffer, null, 1); + renderer.framebuffer.bind(framebuffer, null, 1); - expect(framebuffer.glFramebuffers[CONTEXT_UID].mipLevel).to.equal(1); + expect(framebuffer.glFramebuffers[CONTEXT_UID].mipLevel).toEqual(1); - expect(Array.from(gl.getParameter(gl.VIEWPORT))).to.deep.equal([0, 0, 2, 2]); + expect(Array.from(gl.getParameter(gl.VIEWPORT))).toEqual([0, 0, 2, 2]); - this.renderer.framebuffer.bind(framebuffer, null, 0); + renderer.framebuffer.bind(framebuffer, null, 0); - expect(framebuffer.glFramebuffers[CONTEXT_UID].mipLevel).to.equal(0); + expect(framebuffer.glFramebuffers[CONTEXT_UID].mipLevel).toEqual(0); - expect(Array.from(gl.getParameter(gl.VIEWPORT))).to.deep.equal([0, 0, 4, 4]); + expect(Array.from(gl.getParameter(gl.VIEWPORT))).toEqual([0, 0, 4, 4]); }); - it('should render to with correct frame', function () + it('should render to with correct frame', () => { - const { gl, CONTEXT_UID } = this.renderer; + const { gl } = renderer; const framebuffer = new Framebuffer(4, 4); const frame = new Rectangle(2, 2, 2, 2); - this.renderer.framebuffer.bind(framebuffer, frame, 0); + renderer.framebuffer.bind(framebuffer, frame, 0); - expect(Array.from(gl.getParameter(gl.VIEWPORT))).to.deep.equal([2, 2, 2, 2]); + expect(Array.from(gl.getParameter(gl.VIEWPORT))).toEqual([2, 2, 2, 2]); }); - it('should create an incomplete framebuffer if it has no attachments', function () + it('should create an incomplete framebuffer if it has no attachments', () => { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - const { gl, CONTEXT_UID } = this.renderer; + const { gl } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -80,16 +81,16 @@ describe('FramebufferSystem', function () framebuffer.stencil = false; framebuffer.multisample = MSAA_QUALITY.NONE; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); }); - it('should create a complete framebuffer with a color texture attachment', function () + it('should create a complete framebuffer with a color texture attachment', () => { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -98,28 +99,29 @@ describe('FramebufferSystem', function () framebuffer.multisample = MSAA_QUALITY.NONE; framebuffer.addColorTexture(0); - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.equal(0); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toEqual(0); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).toBeNull(); }); + // eslint-disable-next-line func-names it('should create a complete framebuffer with depth/stencil attachment', function () { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - if (this.renderer.context.webGLVersion === 1 - || this.renderer.framebuffer.msaaSamples === null - || this.renderer.framebuffer.msaaSamples.every((x) => x <= 1)) + if (renderer.context.webGLVersion === 1 + || renderer.framebuffer['msaaSamples'] === null + || renderer.framebuffer['msaaSamples'].every((x) => x <= 1)) { - this.skip(); + return; } - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -127,31 +129,32 @@ describe('FramebufferSystem', function () framebuffer.stencil = true; framebuffer.multisample = MSAA_QUALITY.NONE; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.equal(0); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toEqual(0); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); }); + // eslint-disable-next-line func-names it('should create a complete multisampled framebuffer', function () { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - if (this.renderer.context.webGLVersion === 1 - || this.renderer.framebuffer.msaaSamples === null - || this.renderer.framebuffer.msaaSamples.every((x) => x <= 1)) + if (renderer.context.webGLVersion === 1 + || renderer.framebuffer['msaaSamples'] === null + || renderer.framebuffer['msaaSamples'].every((x) => x <= 1)) { - this.skip(); + return; } - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -159,32 +162,33 @@ describe('FramebufferSystem', function () framebuffer.stencil = false; framebuffer.multisample = MSAA_QUALITY.HIGH; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.be.greaterThan(1); - expect(fbo.msaaBuffer).to.be.not.null; - expect(fbo.stencil).to.be.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toBeGreaterThan(1); + expect(fbo.msaaBuffer).not.toBeNull(); + expect(fbo.stencil).toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); }); + // eslint-disable-next-line func-names it('should create a complete multisampled framebuffer with depth/stencil attachment', function () { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - if (this.renderer.context.webGLVersion === 1 - || this.renderer.framebuffer.msaaSamples === null - || this.renderer.framebuffer.msaaSamples.every((x) => x <= 1)) + if (renderer.context.webGLVersion === 1 + || renderer.framebuffer['msaaSamples'] === null + || renderer.framebuffer['msaaSamples'].every((x) => x <= 1)) { - this.skip(); + return; } - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -192,30 +196,30 @@ describe('FramebufferSystem', function () framebuffer.stencil = true; framebuffer.multisample = MSAA_QUALITY.HIGH; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.be.greaterThan(1); - expect(fbo.msaaBuffer).to.be.not.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toBeGreaterThan(1); + expect(fbo.msaaBuffer).not.toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); }); it('should not create an incomplete framebuffer if it has multiple color attachments and multisampling is requested', - function () + () => { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -225,26 +229,27 @@ describe('FramebufferSystem', function () framebuffer.addColorTexture(0); framebuffer.addColorTexture(1); - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).toBeNull(); }); it('should not create an incomplete framebuffer if it has depth texture and multisampling is requested', + // eslint-disable-next-line func-names function () { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - if (!this.renderer.framebuffer.writeDepthTexture) + if (!renderer.framebuffer.writeDepthTexture) { - this.skip(); + return; } - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 4); @@ -253,20 +258,20 @@ describe('FramebufferSystem', function () framebuffer.multisample = MSAA_QUALITY.HIGH; framebuffer.addDepthTexture(); - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).toBeNull(); }); - it('should succeed to resize framebuffer', function () + it('should succeed to resize framebuffer', () => { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 8); @@ -274,49 +279,50 @@ describe('FramebufferSystem', function () framebuffer.stencil = true; framebuffer.multisample = MSAA_QUALITY.NONE; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.equal(0); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toEqual(0); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(4); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(8); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(4); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(8); framebuffer.resize(16, 32); - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.equal(0); - expect(fbo.msaaBuffer).to.be.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toEqual(0); + expect(fbo.msaaBuffer).toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(16); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(32); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(16); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(32); }); + // eslint-disable-next-line func-names it('should succeed to resize multisampled framebuffer', function () { - this.renderer.framebuffer.contextChange(); + renderer.framebuffer['contextChange'](); - if (this.renderer.context.webGLVersion === 1 - || this.renderer.framebuffer.msaaSamples === null - || this.renderer.framebuffer.msaaSamples.every((x) => x <= 1)) + if (renderer.context.webGLVersion === 1 + || renderer.framebuffer['msaaSamples'] === null + || renderer.framebuffer['msaaSamples'].every((x) => x <= 1)) { - this.skip(); + return; } - const { gl, CONTEXT_UID } = this.renderer; + const { gl, CONTEXT_UID } = renderer; const framebuffer = new Framebuffer(4, 8); @@ -324,46 +330,46 @@ describe('FramebufferSystem', function () framebuffer.stencil = true; framebuffer.multisample = MSAA_QUALITY.HIGH; - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); const fbo = framebuffer.glFramebuffers[CONTEXT_UID]; - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.be.greaterThan(1); - expect(fbo.msaaBuffer).to.be.not.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toBeGreaterThan(1); + expect(fbo.msaaBuffer).not.toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(4); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(8); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(4); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(8); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(4); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(8); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(4); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(8); framebuffer.resize(16, 32); - this.renderer.framebuffer.bind(framebuffer); + renderer.framebuffer.bind(framebuffer); - expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).to.equal(gl.FRAMEBUFFER_COMPLETE); - expect(fbo.multisample).to.be.greaterThan(1); - expect(fbo.msaaBuffer).to.be.not.null; - expect(fbo.stencil).to.be.not.null; + expect(gl.checkFramebufferStatus(gl.FRAMEBUFFER)).toEqual(gl.FRAMEBUFFER_COMPLETE); + expect(fbo.multisample).toBeGreaterThan(1); + expect(fbo.msaaBuffer).not.toBeNull(); + expect(fbo.stencil).not.toBeNull(); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.msaaBuffer); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(16); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(32); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(16); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(32); gl.bindRenderbuffer(gl.RENDERBUFFER, fbo.stencil); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).to.equal(fbo.multisample); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).to.equal(16); - expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).to.equal(32); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)).toEqual(fbo.multisample); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)).toEqual(16); + expect(gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)).toEqual(32); }); }); diff --git a/packages/core/test/Geometry.tests.ts b/packages/core/test/Geometry.tests.ts index 317755e36ca..591afadf120 100644 --- a/packages/core/test/Geometry.tests.ts +++ b/packages/core/test/Geometry.tests.ts @@ -1,5 +1,4 @@ import { Buffer, Geometry, Program, Renderer, Shader, Texture } from '@pixi/core'; -import { expect } from 'chai'; const vert = ` attribute vec2 aVertexPosition; @@ -30,15 +29,15 @@ void main() { gl_FragColor = texture2D(uSampler, vUvs); }`; -describe('Geometry', function () +describe('Geometry', () => { - it('should dispose shared index buffer after all geometries were disposed/destroyed', function () + it('should dispose shared index buffer after all geometries were disposed/destroyed', () => { const renderer = new Renderer({ width: 1, height: 1 }); try { - const indices = new Buffer([0, 1, 2, 0, 2, 3], true, true); + const indices = new Buffer(new Float32Array([0, 1, 2, 0, 2, 3]), true, true); const geometry1 = new Geometry(); const geometry2 = new Geometry(); const prog = new Program(vert, frag); @@ -55,10 +54,10 @@ describe('Geometry', function () renderer.geometry.bind(geometry2, shader); geometry1.destroy(); - expect(indices.data).to.be.not.null; - expect(Object.keys(indices._glBuffers).length).to.equal(1); + expect(indices.data).not.toBeNull(); + expect(Object.keys(indices._glBuffers).length).toEqual(1); geometry2.destroy(); - expect(Object.keys(indices._glBuffers).length).to.equal(0); + expect(Object.keys(indices._glBuffers).length).toEqual(0); } finally { @@ -66,13 +65,13 @@ describe('Geometry', function () } }); - it('should dispose buffer if geometry is used by two shaders', function () + it('should dispose buffer if geometry is used by two shaders', () => { const renderer = new Renderer({ width: 1, height: 1 }); try { - const indices = new Buffer([0, 1, 2, 0, 2, 3], true, true); + const indices = new Buffer(new Float32Array([0, 1, 2, 0, 2, 3]), true, true); const geometry = new Geometry(); const prog = new Program(vert, frag); const prog2 = new Program(vert2, frag); @@ -87,15 +86,15 @@ describe('Geometry', function () renderer.geometry.bind(geometry, shader2); // 2 signatures and 2 by shader-ids - expect(Object.keys(geometry.glVertexArrayObjects).length).to.equal(1); - expect(Object.keys(geometry.glVertexArrayObjects[renderer.CONTEXT_UID]).length).to.equal(4); - expect(Object.keys(renderer.geometry.managedGeometries).length).to.equal(1); - expect(Object.keys(indices._glBuffers).length).to.equal(1); - expect(indices._glBuffers[renderer.CONTEXT_UID].refCount).to.equal(1); + expect(Object.keys(geometry.glVertexArrayObjects).length).toEqual(1); + expect(Object.keys(geometry.glVertexArrayObjects[renderer.CONTEXT_UID]).length).toEqual(4); + expect(Object.keys(renderer.geometry.managedGeometries).length).toEqual(1); + expect(Object.keys(indices._glBuffers).length).toEqual(1); + expect(indices._glBuffers[renderer.CONTEXT_UID].refCount).toEqual(1); geometry.dispose(); - expect(Object.keys(geometry.glVertexArrayObjects).length).to.equal(0); - expect(Object.keys(renderer.geometry.managedGeometries).length).to.equal(0); - expect(Object.keys(indices._glBuffers).length).to.equal(0); + expect(Object.keys(geometry.glVertexArrayObjects).length).toEqual(0); + expect(Object.keys(renderer.geometry.managedGeometries).length).toEqual(0); + expect(Object.keys(indices._glBuffers).length).toEqual(0); geometry.destroy(); } finally @@ -104,7 +103,7 @@ describe('Geometry', function () } }); - it('should correctly merge the index buffers of geometries with different length', function () + it('should correctly merge the index buffers of geometries with different length', () => { const geom0 = new Geometry() .addAttribute('aVertexPosition', [0, 0, 1, 1, 2, 2], 2) @@ -115,16 +114,16 @@ describe('Geometry', function () const geom = Geometry.merge([geom0, geom1]); - expect([...geom.getIndex().data]).to.have.members([0, 1, 2, 3, 4, 5, 6]); + expect([...(geom.getIndex().data) as unknown as number[]]).toEqual(expect.arrayContaining([0, 1, 2, 3, 4, 5, 6])); }); - it('should create one VAO for shaders with the same attributes and same location specifiers', function () + it('should create one VAO for shaders with the same attributes and same location specifiers', () => { const renderer = new Renderer({ width: 1, height: 1 }); try { - const indices = new Buffer([0, 1, 2], true, true); + const indices = new Buffer(new Float32Array([0, 1, 2]), true, true); const prog1 = new Program(`\ #version 300 es @@ -175,13 +174,13 @@ describe('Geometry', function () renderer.geometry.bind(geometry, shader1); - const vao1 = renderer.geometry._activeVao; + const vao1 = renderer.geometry['_activeVao']; renderer.geometry.bind(geometry, shader2); - const vao2 = renderer.geometry._activeVao; + const vao2 = renderer.geometry['_activeVao']; - expect(vao1).to.equal(vao2); + expect(vao1).toEqual(vao2); geometry.destroy(); } @@ -191,13 +190,13 @@ describe('Geometry', function () } }); - it('should create different VAOs for shaders with the same attributes but different location specifiers', function () + it('should create different VAOs for shaders with the same attributes but different location specifiers', () => { const renderer = new Renderer({ width: 1, height: 1 }); try { - const indices = new Buffer([0, 1, 2], true, true); + const indices = new Buffer(new Float32Array([0, 1, 2]), true, true); const prog1 = new Program(`\ #version 300 es @@ -248,13 +247,13 @@ describe('Geometry', function () renderer.geometry.bind(geometry, shader1); - const vao1 = renderer.geometry._activeVao; + const vao1 = renderer.geometry['_activeVao']; renderer.geometry.bind(geometry, shader2); - const vao2 = renderer.geometry._activeVao; + const vao2 = renderer.geometry['_activeVao']; - expect(vao1).to.not.equal(vao2); + expect(vao1).not.toBe(vao2); geometry.destroy(); } @@ -264,15 +263,16 @@ describe('Geometry', function () } }); - it('should create compatible VAOs if GeometrySystem.checkCompatibility is disabled', function () + it('should create compatible VAOs if GeometrySystem.checkCompatibility is disabled', () => { const renderer = new Renderer({ width: 1, height: 1 }); - renderer.geometry.checkCompatibility = function () {}; + // eslint-disable-next-line @typescript-eslint/no-empty-function + renderer.geometry['checkCompatibility'] = () => {}; try { - const indices = new Buffer([0, 1, 2], true, true); + const indices = new Buffer(new Float32Array([0, 1, 2]), true, true); const prog1 = new Program(`\ #version 100 @@ -317,13 +317,13 @@ describe('Geometry', function () renderer.geometry.bind(geometry, shader1); - const vao1 = renderer.geometry._activeVao; + const vao1 = renderer.geometry['_activeVao']; renderer.geometry.bind(geometry, shader2); - const vao2 = renderer.geometry._activeVao; + const vao2 = renderer.geometry['_activeVao']; - expect(vao1).to.not.equal(vao2); + expect(vao1).not.toBe(vao2); geometry.destroy(); } diff --git a/packages/core/test/ImageBitmapResource.tests.ts b/packages/core/test/ImageBitmapResource.tests.ts index c90fd1b83e6..d7b7010377d 100644 --- a/packages/core/test/ImageBitmapResource.tests.ts +++ b/packages/core/test/ImageBitmapResource.tests.ts @@ -1,24 +1,23 @@ +import type { BaseTexture } from '@pixi/core'; import { ImageBitmapResource } from '@pixi/core'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('ImageBitmapResource', function () +describe('ImageBitmapResource', () => { - it('should create new dimension-less resource', async function () + it('should create new dimension-less resource', async () => { const canvas = document.createElement('canvas'); const bitmap = await createImageBitmap(canvas); const resource = new ImageBitmapResource(bitmap); - expect(resource.width).to.equal(canvas.width); - expect(resource.height).to.equal(canvas.height); - expect(resource.valid).to.be.true; + expect(resource.width).toEqual(canvas.width); + expect(resource.height).toEqual(canvas.height); + expect(resource.valid).toBe(true); resource.destroy(); }); - it('should create new valid resource', async function () + it('should create new valid resource', async () => { const canvas = document.createElement('canvas'); @@ -28,44 +27,44 @@ describe('ImageBitmapResource', function () const bitmap = await createImageBitmap(canvas); const resource = new ImageBitmapResource(bitmap); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(200); - expect(resource.valid).to.be.true; + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(200); + expect(resource.valid).toBe(true); resource.destroy(); }); - it('should fire resize event on bind', async function () + it('should fire resize event on bind', async () => { const canvas = document.createElement('canvas'); const bitmap = await createImageBitmap(canvas); const resource = new ImageBitmapResource(bitmap); - const baseTexture = { setRealSize: sinon.stub() }; + const baseTexture = { setRealSize: jest.fn() }; - resource.bind(baseTexture); + resource.bind(baseTexture as unknown as BaseTexture); - expect(baseTexture.setRealSize.calledOnce).to.be.true; + expect(baseTexture.setRealSize).toBeCalledTimes(1); - resource.unbind(baseTexture); + resource.unbind(baseTexture as unknown as BaseTexture); resource.destroy(); }); - it('should fire manual update event', async function () + it('should fire manual update event', async () => { const canvas = document.createElement('canvas'); const bitmap = await createImageBitmap(canvas); const resource = new ImageBitmapResource(bitmap); - const baseTexture = { update: sinon.stub() }; + const baseTexture = { update: jest.fn() }; - resource.bind(baseTexture); + resource.bind(baseTexture as unknown as BaseTexture); - expect(baseTexture.update.called).to.be.false; + expect(baseTexture.update).not.toHaveBeenCalled(); resource.update(); - expect(baseTexture.update.calledOnce).to.be.true; + expect(baseTexture.update).toBeCalledTimes(1); - resource.unbind(baseTexture); + resource.unbind(baseTexture as unknown as BaseTexture); resource.destroy(); }); }); diff --git a/packages/core/test/ImageResource.tests.ts b/packages/core/test/ImageResource.tests.ts index 97173e6453e..cf31a105935 100644 --- a/packages/core/test/ImageResource.tests.ts +++ b/packages/core/test/ImageResource.tests.ts @@ -1,30 +1,31 @@ import { ImageResource, BaseTexture, Renderer } from '@pixi/core'; import { settings } from '@pixi/settings'; import path from 'path'; -import { expect } from 'chai'; -describe('ImageResource', function () +describe('ImageResource', () => { - before(function () + let slugUrl: string; + + beforeAll(() => { - this.slugUrl = path.resolve(__dirname, 'resources', 'slug.png'); + slugUrl = path.resolve(__dirname, 'resources', 'slug.png'); }); - it('should create new dimension-less resource', function () + it('should create new dimension-less resource', () => { const image = new Image(); const resource = new ImageResource(image); - expect(resource.width).to.equal(0); - expect(resource.height).to.equal(0); - expect(resource.valid).to.be.false; - expect(resource.url).to.equal(''); + expect(resource.width).toEqual(0); + expect(resource.height).toEqual(0); + expect(resource.valid).toBe(false); + expect(resource.url).toEqual(''); resource.destroy(); }); - it('should destroy resource multiple times', function () + it('should destroy resource multiple times', () => { const resource = new ImageResource(new Image()); @@ -32,27 +33,27 @@ describe('ImageResource', function () resource.destroy(); }); - it('should create new valid resource from HTMLImageElement', function () + it('should create new valid resource from HTMLImageElement', () => { const image = new Image(); - image.src = this.slugUrl; + image.src = slugUrl; const resource = new ImageResource(image); - expect(resource.width).to.equal(0); - expect(resource.height).to.equal(0); - expect(resource.valid).to.be.false; - expect(resource.url).to.equal(image.src); + expect(resource.width).toEqual(0); + expect(resource.height).toEqual(0); + expect(resource.valid).toBe(false); + expect(resource.url).toEqual(image.src); resource.destroy(); }); - it('should handle the loaded event with createBitmapImage', function () + it('should handle the loaded event with createBitmapImage', () => { const image = new Image(); - image.src = this.slugUrl; + image.src = slugUrl; const resource = new ImageResource(image, { autoLoad: false, @@ -61,19 +62,19 @@ describe('ImageResource', function () return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); - expect(resource.valid).to.be.true; - expect(resource.bitmap).to.be.instanceof(ImageBitmap); + expect(res).toEqual(resource); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); + expect(resource.valid).toBe(true); + expect(resource.bitmap).toBeInstanceOf(ImageBitmap); }); }); - it('should handle the loaded event with no createBitmapImage', function () + it('should handle the loaded event with no createBitmapImage', () => { const image = new Image(); - image.src = this.slugUrl; + image.src = slugUrl; const resource = new ImageResource(image, { autoLoad: false, @@ -82,15 +83,15 @@ describe('ImageResource', function () return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); - expect(resource.valid).to.be.true; - expect(resource.bitmap).to.be.null; + expect(res).toEqual(resource); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); + expect(resource.valid).toBe(true); + expect(resource.bitmap).toBeNull(); }); }); - it('should handle error when resource is broken', function () + it('should handle error when resource is broken', () => { const image = new Image(); @@ -103,97 +104,99 @@ describe('ImageResource', function () return resource.load().catch((error) => { - expect(error).to.be.not.null; + expect(error).not.toBeNull(); }); }); - it('should handle the loaded event with createBitmapImage using global setting', function () + it('should handle the loaded event with createBitmapImage using global setting', () => { const old = settings.CREATE_IMAGE_BITMAP; const image = new Image(); settings.CREATE_IMAGE_BITMAP = true; - image.src = this.slugUrl; + image.src = slugUrl; const resource = new ImageResource(image, { autoLoad: false }); return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(resource.createBitmap).to.equal(true); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); - expect(resource.valid).to.be.true; - expect(resource.bitmap).to.be.instanceof(ImageBitmap); + expect(res).toEqual(resource); + expect(resource.createBitmap).toEqual(true); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); + expect(resource.valid).toBe(true); + expect(resource.bitmap).toBeInstanceOf(ImageBitmap); settings.CREATE_IMAGE_BITMAP = old; }); }); - it('should handle the loaded event with no createBitmapImage using global setting', function () + it('should handle the loaded event with no createBitmapImage using global setting', () => { const old = settings.CREATE_IMAGE_BITMAP; const image = new Image(); settings.CREATE_IMAGE_BITMAP = false; - image.src = this.slugUrl; + image.src = slugUrl; const resource = new ImageResource(image, { autoLoad: false }); return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(resource.createBitmap).to.equal(false); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); - expect(resource.valid).to.be.true; - expect(resource.bitmap).to.be.null; + expect(res).toEqual(resource); + expect(resource.createBitmap).toEqual(false); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); + expect(resource.valid).toBe(true); + expect(resource.bitmap).toBeNull(); settings.CREATE_IMAGE_BITMAP = old; }); }); - describe('alphaMode behaviour', function () + describe('alphaMode behaviour', () => { - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should override BaseTexture alphaMode if specified', function () + it('should override BaseTexture alphaMode if specified', () => { const image = new Image(); const resource = new ImageResource(image, { autoLoad: false, alphaMode: 2 }); const baseTexture = new BaseTexture(resource); - image.src = this.slugUrl; + image.src = slugUrl; return resource.load(false).then(() => { - this.renderer.texture.bind(baseTexture); - expect(baseTexture.alphaMode).to.equal(2); + renderer.texture.bind(baseTexture); + expect(baseTexture.alphaMode).toEqual(2); }); }); - it('should not override BaseTexture alphaMode if not specified', function () + it('should not override BaseTexture alphaMode if not specified', () => { const image = new Image(); const resource = new ImageResource(image, { autoLoad: false }); const baseTexture = new BaseTexture(resource); baseTexture.alphaMode = 2; - expect(resource.alphaMode).to.be.null; + expect(resource.alphaMode).toBeNull(); - image.src = this.slugUrl; + image.src = slugUrl; return resource.load(false).then(() => { - this.renderer.texture.bind(baseTexture); - expect(baseTexture.alphaMode).to.equal(2); + renderer.texture.bind(baseTexture); + expect(baseTexture.alphaMode).toEqual(2); }); }); }); diff --git a/packages/core/test/MaskSystem.tests.ts b/packages/core/test/MaskSystem.tests.ts index 70c9eea7cdd..41d5b80ccd2 100644 --- a/packages/core/test/MaskSystem.tests.ts +++ b/packages/core/test/MaskSystem.tests.ts @@ -1,25 +1,35 @@ -import { MASK_TYPES, MSAA_QUALITY } from '@pixi/constants'; -import { Rectangle, Matrix } from '@pixi/math'; -import { Renderer, MaskData, RenderTexture, Filter, Texture, BaseTexture, CanvasResource, - SpriteMaskFilter } from '@pixi/core'; +import { MASK_TYPES, COLOR_MASK_BITS } from '@pixi/constants'; +import type { + IFilterTarget, + IMaskTarget } from '@pixi/core'; +import { + BaseTexture, + CanvasResource, + Filter, + MaskData, + Renderer, + RenderTexture, + SpriteMaskFilter, + Texture +} from '@pixi/core'; +import { Container } from '@pixi/display'; import { Graphics } from '@pixi/graphics'; +import { Matrix, Rectangle } from '@pixi/math'; import { Sprite } from '@pixi/sprite'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('MaskSystem', function () +describe('MaskSystem', () => { - function onePixelMask(worldTransform) + function onePixelMask(worldTransform: Matrix | Record): IMaskTarget { return { isFastRect() { return true; }, worldTransform: worldTransform || Matrix.IDENTITY, getBounds() { return new Rectangle(0, 0, 1, 1); }, render() { /* nothing*/ }, - }; + } as unknown as IMaskTarget; } - function createColorTexture(color) + function createColorTexture(color: CanvasRenderingContext2D['fillStyle']) { const canvas = document.createElement('canvas'); @@ -34,14 +44,19 @@ describe('MaskSystem', function () return new Texture(new BaseTexture(new CanvasResource(canvas))); } - before(function () + let renderer: Renderer; + let textureRed: Texture; + let textureGreen: Texture; + let spriteMaskFilterGreen: SpriteMaskFilter; + + beforeAll(() => { - this.renderer = new Renderer(); - this.renderer.mask.enableScissor = true; - this.textureRed = createColorTexture('#ff0000'); - this.textureGreen = createColorTexture('#00ff00'); + renderer = new Renderer(); + renderer.mask.enableScissor = true; + textureRed = createColorTexture('#ff0000'); + textureGreen = createColorTexture('#00ff00'); // Like SpriteMaskFilter, but with green instead of red channel - this.spriteMaskFilterGreen = new SpriteMaskFilter(undefined, `\ + spriteMaskFilterGreen = new SpriteMaskFilter(undefined, `\ varying vec2 vMaskCoord; varying vec2 vTextureCoord; @@ -69,194 +84,197 @@ describe('MaskSystem', function () }`); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; - this.textureRed.destroy(true); - this.textureRed = null; - this.textureGreen.destroy(true); - this.textureGreen = null; - this.spriteMaskFilterGreen.destroy(); - this.spriteMaskFilterGreen = null; + renderer.destroy(); + renderer = null; + textureRed.destroy(true); + textureRed = null; + textureGreen.destroy(true); + textureGreen = null; + spriteMaskFilterGreen.destroy(); + spriteMaskFilterGreen = null; }); - it('should have scissor-masks enabled', function () + it('should have scissor-masks enabled', () => { - expect(this.renderer.mask.enableScissor).to.equal(true); + expect(renderer.mask.enableScissor).toEqual(true); }); - it('should use scissor masks with axis aligned squares', function () + it('should use scissor masks with axis aligned squares', () => { - const context = {}; + const context = {} as IMaskTarget; const maskObject = onePixelMask({ a: 1, b: 0, c: 0, d: 1 }); const maskObject2 = onePixelMask({ a: 0, b: 1, c: 1, d: 0 }); - this.renderer.mask.push(context, maskObject); + renderer.mask.push(context, maskObject); - expect(this.renderer.scissor.getStackLength()).to.equal(1); + expect(renderer.scissor.getStackLength()).toEqual(1); - this.renderer.mask.push(context, maskObject2); + renderer.mask.push(context, maskObject2); - expect(this.renderer.scissor.getStackLength()).to.equal(2); + expect(renderer.scissor.getStackLength()).toEqual(2); - this.renderer.mask.pop(context, maskObject2); + renderer.mask.pop(context); - expect(this.renderer.scissor.getStackLength()).to.equal(1); + expect(renderer.scissor.getStackLength()).toEqual(1); - this.renderer.mask.pop(context, maskObject); + renderer.mask.pop(context); - expect(this.renderer.scissor.getStackLength()).to.equal(0); + expect(renderer.scissor.getStackLength()).toEqual(0); }); - it('should return maskData to pool if it does not belong in the object', function () + it('should return maskData to pool if it does not belong in the object', () => { - const context = {}; + const context: IMaskTarget = {} as IMaskTarget; const maskObject = onePixelMask({ a: 1, b: 0, c: 0, d: 1 }); - this.renderer.mask.maskDataPool.length = 0; - this.renderer.mask.push(context, maskObject); - this.renderer.mask.pop(context, maskObject); + renderer.mask['maskDataPool'].length = 0; + renderer.mask.push(context, maskObject); + renderer.mask.pop(context); - const maskData = this.renderer.mask.maskDataPool[0]; + const maskData = renderer.mask['maskDataPool'][0]; - expect(maskData).to.exist; - expect(maskData._scissorCounter).to.equal(1); + expect(maskData).toBeDefined(); + expect(maskData._scissorCounter).toEqual(1); }); - it('should not put maskData to pool if it belongs to object', function () + it('should not put maskData to pool if it belongs to object', () => { - const context = {}; + const context: IMaskTarget = {} as IMaskTarget; const maskData = new MaskData(onePixelMask({ a: 1, b: 0, c: 0, d: 1 })); - this.renderer.mask.maskDataPool.length = 0; + renderer.mask['maskDataPool'].length = 0; for (let i = 0; i < 2; i++) { // repeat two times just to be sure - this.renderer.mask.push(context, maskData); - this.renderer.mask.pop(context, maskData); + renderer.mask.push(context, maskData); + renderer.mask.pop(context); - expect(maskData._scissorCounter).to.equal(1); - expect(this.renderer.mask.maskDataPool.length).to.equal(0); + expect(maskData._scissorCounter).toEqual(1); + expect(renderer.mask['maskDataPool'].length).toEqual(0); } }); - it('should not use scissor masks with non axis aligned squares', function () + it('should not use scissor masks with non axis aligned squares', () => { - const context = {}; + const context: IMaskTarget = {} as IMaskTarget; const maskObject = onePixelMask({ a: 0.1, b: 2, c: 2, d: -0.1 }); - this.renderer.mask.push(context, maskObject); + renderer.mask.push(context, maskObject); - expect(this.renderer.scissor.getStackLength()).to.equal(0); + expect(renderer.scissor.getStackLength()).toEqual(0); - this.renderer.mask.pop(context, maskObject); + renderer.mask.pop(context); }); - it('should apply scissor with transform on canvas or renderTexture', function () + it('should apply scissor with transform on canvas or renderTexture', () => { - const context = {}; + const context: IMaskTarget = {} as IMaskTarget; const maskObject = { isFastRect() { return true; }, worldTransform: Matrix.IDENTITY, getBounds() { return new Rectangle(2, 3, 6, 5); }, render() { /* nothing*/ }, - }; + } as unknown as IMaskTarget; - this.renderer.resolution = 2; - this.renderer.resize(30, 30); + renderer._view.resolution = 2; + renderer.resize(30, 30); const rt = RenderTexture.create({ width: 20, height: 20, resolution: 3 }); - const scissor = sinon.spy(this.renderer.gl, 'scissor'); + const scissor = jest.spyOn(renderer.gl, 'scissor'); - this.renderer.projection.transform = new Matrix(1, 0, 0, 1, 0.5, 1); - this.renderer.mask.push(context, maskObject); - this.renderer.mask.pop(context, maskObject); + renderer.projection.transform = new Matrix(1, 0, 0, 1, 0.5, 1); + renderer.mask.push(context, maskObject); + renderer.mask.pop(context); // now , lets try it for renderTexture - this.renderer.renderTexture.bind(rt); + renderer.renderTexture.bind(rt); - this.renderer.mask.push(context, maskObject); - this.renderer.mask.pop(context, maskObject); + renderer.mask.push(context, maskObject); + renderer.mask.pop(context); - expect(scissor.calledTwice).to.be.true; + expect(scissor).toBeCalledTimes(2); // result Y is 2 because after transform y=8 h=10 and renderer H=60 is inverted , 8-18 becomes 52-42, e.g. Y=2 - expect(scissor.args[0]).to.eql([Math.round(5), Math.round(42), Math.round(12), Math.round(10)]); + expect(scissor.mock.calls[0]).toEqual([Math.round(5), Math.round(42), Math.round(12), Math.round(10)]); // resolution is 3 , and Y is not reversed - expect(scissor.args[1]).to.eql([Math.round(7.5), Math.round(12), Math.round(18), Math.round(15)]); + expect(scissor.mock.calls[1]).toEqual([Math.round(7.5), Math.round(12), Math.round(18), Math.round(15)]); rt.destroy(true); - this.renderer.projection.transform = null; - this.renderer.resolution = 1; + + renderer.projection.transform = null; + renderer._view.resolution = 1; }); + // eslint-disable-next-line func-names it('should correctly calculate alpha mask area if filter is present', function () { // fixes slow runs on CI #6604 - this.timeout(5000); + jest.setTimeout(5000); // the bug was fixed in #5444 - this.renderer.resize(10, 10); + renderer.resize(10, 10); - const filteredObject = { + const filteredObject: IFilterTarget = { getBounds() { return new Rectangle(0, 0, 10, 10); }, render() { /* nothing*/ }, - }; + } as unknown as IFilterTarget; const maskBounds = new Rectangle(2, 3, 6, 5); const maskObject = { isSprite: true, _texture: Texture.WHITE, + // @ts-expect-error - mocking IMaskTarget get texture() { return this._texture; }, anchor: { x: 0, y: 0 }, isFastRect() { return true; }, worldTransform: Matrix.IDENTITY, getBounds() { return maskBounds.clone(); }, - }; + } as unknown as IMaskTarget; const filters = [new Filter()]; - const maskSystem = this.renderer.mask; + const maskSystem = renderer.mask; for (let i = 0; i < 6; i++) { - this.renderer.filter.push(filteredObject, filters); - maskSystem.push(filteredObject, maskObject); - expect(maskSystem.maskStack.length).to.equal(1); - expect(maskSystem.maskStack[0].type).to.equal(MASK_TYPES.SPRITE); - expect(this.renderer.renderTexture.current).to.exist; + renderer.filter.push(filteredObject, filters); + maskSystem.push(filteredObject as IMaskTarget, maskObject); + expect(maskSystem['maskStack'].length).toEqual(1); + expect(maskSystem['maskStack'][0].type).toEqual(MASK_TYPES.SPRITE); + expect(renderer.renderTexture.current).toBeDefined(); - const filterArea = this.renderer.renderTexture.current.filterFrame; + const filterArea = renderer.renderTexture.current.filterFrame; const expected = maskBounds.clone().ceil(); expected.fit(filteredObject.getBounds()); - expect(filterArea).to.exist; - expect(filterArea.x).to.equal(expected.x); - expect(filterArea.y).to.equal(expected.y); - expect(filterArea.width).to.equal(expected.width); - expect(filterArea.height).to.equal(expected.height); + expect(filterArea).toBeDefined(); + expect(filterArea.x).toEqual(expected.x); + expect(filterArea.y).toEqual(expected.y); + expect(filterArea.width).toEqual(expected.width); + expect(filterArea.height).toEqual(expected.height); - maskSystem.pop(filteredObject); - this.renderer.filter.pop(); - expect(maskSystem.maskStack.length).to.equal(0); - expect(this.renderer.renderTexture.current).to.be.null; + maskSystem.pop(filteredObject as IMaskTarget); + renderer.filter.pop(); + expect(maskSystem['maskStack'].length).toEqual(0); + expect(renderer.renderTexture.current).toBeNull(); maskBounds.x += 1.0; maskBounds.y += 0.5; } }); - it('should render correctly without a custom sprite mask filter and a red texture sprite mask', function () + it('should render correctly without a custom sprite mask filter and a red texture sprite mask', () => { const graphics = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 1, 1).endFill(); - graphics.mask = new MaskData(new Sprite(this.textureRed)); + graphics.mask = new MaskData(new Sprite(textureRed)); - const renderTexture = this.renderer.generateTexture(graphics); + const renderTexture = renderer.generateTexture(graphics); graphics.destroy(true); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array(4); - const gl = this.renderer.gl; + const gl = renderer.gl; gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); @@ -264,26 +282,26 @@ describe('MaskSystem', function () const [r, g, b, a] = pixel; - expect(r).to.equal(0xff); - expect(g).to.equal(0xff); - expect(b).to.equal(0xff); - expect(a).to.equal(0xff); + expect(r).toEqual(0xff); + expect(g).toEqual(0xff); + expect(b).toEqual(0xff); + expect(a).toEqual(0xff); }); - it('should render correctly without a custom sprite mask filter and a green texture sprite mask', function () + it('should render correctly without a custom sprite mask filter and a green texture sprite mask', () => { const graphics = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 1, 1).endFill(); - graphics.mask = new MaskData(new Sprite(this.textureGreen)); + graphics.mask = new MaskData(new Sprite(textureGreen)); - const renderTexture = this.renderer.generateTexture(graphics); + const renderTexture = renderer.generateTexture(graphics); graphics.destroy(true); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array(4); - const gl = this.renderer.gl; + const gl = renderer.gl; gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); @@ -291,27 +309,27 @@ describe('MaskSystem', function () const [r, g, b, a] = pixel; - expect(r).to.equal(0x00); - expect(g).to.equal(0x00); - expect(b).to.equal(0x00); - expect(a).to.equal(0x00); + expect(r).toEqual(0x00); + expect(g).toEqual(0x00); + expect(b).toEqual(0x00); + expect(a).toEqual(0x00); }); - it('should render correctly with acustom sprite mask filter and a red texture sprite mask', function () + it('should render correctly with acustom sprite mask filter and a red texture sprite mask', () => { const graphics = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 1, 1).endFill(); - graphics.mask = new MaskData(new Sprite(this.textureRed)); - graphics.mask.filter = this.spriteMaskFilterGreen; + graphics.mask = new MaskData(new Sprite(textureRed)); + graphics.mask.filter = spriteMaskFilterGreen; - const renderTexture = this.renderer.generateTexture(graphics); + const renderTexture = renderer.generateTexture(graphics); graphics.destroy(true); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array(4); - const gl = this.renderer.gl; + const gl = renderer.gl; gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); @@ -319,27 +337,27 @@ describe('MaskSystem', function () const [r, g, b, a] = pixel; - expect(r).to.equal(0x00); - expect(g).to.equal(0x00); - expect(b).to.equal(0x00); - expect(a).to.equal(0x00); + expect(r).toEqual(0x00); + expect(g).toEqual(0x00); + expect(b).toEqual(0x00); + expect(a).toEqual(0x00); }); - it('should render correctly with a custom sprite mask filter and a green texture sprite mask', function () + it('should render correctly with a custom sprite mask filter and a green texture sprite mask', () => { const graphics = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 1, 1).endFill(); - graphics.mask = new MaskData(new Sprite(this.textureGreen)); - graphics.mask.filter = this.spriteMaskFilterGreen; + graphics.mask = new MaskData(new Sprite(textureGreen)); + graphics.mask.filter = spriteMaskFilterGreen; - const renderTexture = this.renderer.generateTexture(graphics); + const renderTexture = renderer.generateTexture(graphics); graphics.destroy(true); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array(4); - const gl = this.renderer.gl; + const gl = renderer.gl; gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); @@ -347,53 +365,163 @@ describe('MaskSystem', function () const [r, g, b, a] = pixel; - expect(r).to.equal(0xff); - expect(g).to.equal(0xff); - expect(b).to.equal(0xff); - expect(a).to.equal(0xff); + expect(r).toEqual(0xff); + expect(g).toEqual(0xff); + expect(b).toEqual(0xff); + expect(a).toEqual(0xff); }); - it('should restore sprite of current sprite mask filter after pop', function () + it('should restore sprite of current sprite mask filter after pop', () => { const renderTexture = RenderTexture.create({ width: 1, height: 1 }); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const graphics1 = new Graphics(); const graphics2 = new Graphics(); - const sprite1 = new Sprite(this.textureRed); - const sprite2 = new Sprite(this.textureGreen); + const sprite1 = new Sprite(textureRed); + const sprite2 = new Sprite(textureGreen); const maskData1 = new MaskData(sprite1); const maskData2 = new MaskData(sprite2); - maskData1.filter = this.spriteMaskFilterGreen; - maskData2.filter = this.spriteMaskFilterGreen; + maskData1.filter = spriteMaskFilterGreen; + maskData2.filter = spriteMaskFilterGreen; - expect(maskData1.filter.maskSprite).to.be.null; - expect(maskData2.filter.maskSprite).to.be.null; + expect(maskData1.filter.maskSprite).toBeNull(); + expect(maskData2.filter.maskSprite).toBeNull(); graphics1.mask = maskData1; graphics2.mask = maskData2; - this.renderer.mask.push(graphics1, maskData1); + renderer.mask.push(graphics1, maskData1); + + expect(maskData1.filter.maskSprite).toEqual(sprite1); + + renderer.mask.push(graphics2, maskData2); + + expect(maskData2.filter.maskSprite).toEqual(sprite2); + + renderer.mask.pop(graphics2); + + expect(maskData1.filter.maskSprite).toEqual(sprite1); + + renderer.mask.pop(graphics1); + + expect(maskData1.filter.maskSprite).toBeNull(); + expect(maskData2.filter.maskSprite).toBeNull(); + + renderTexture.destroy(true); + }); + + it('should render correctly with nested color and stencil masks', () => + { + const stage = new Container(); + const container1 = new Container(); + const container2 = new Container(); + const graphics = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 2, 1).endFill(); + const mask = new Graphics().beginFill(0xffffff, 1.0).drawPolygon(1, 0, 2, 0, 2, 1, 1, 1).endFill(); + + stage.addChild(container1, mask); + container1.addChild(container2); + container2.addChild(graphics); + + stage.mask = new MaskData(); + stage.mask.colorMask = COLOR_MASK_BITS.RED | COLOR_MASK_BITS.GREEN | COLOR_MASK_BITS.ALPHA; + mask.mask = new MaskData(); + mask.mask.colorMask = COLOR_MASK_BITS.RED | COLOR_MASK_BITS.ALPHA; + container1.mask = new MaskData(mask); + container2.mask = new MaskData(mask); + graphics.mask = new MaskData(); + graphics.mask.colorMask = COLOR_MASK_BITS.GREEN | COLOR_MASK_BITS.BLUE | COLOR_MASK_BITS.ALPHA; - expect(maskData1.filter.maskSprite).to.equal(sprite1); + const renderTexture = renderer.generateTexture(stage, { region: new Rectangle(0, 0, 2, 1) }); - this.renderer.mask.push(graphics2, maskData2); + expect(renderTexture.width).toEqual(2); + expect(renderTexture.height).toEqual(1); - expect(maskData2.filter.maskSprite).to.equal(sprite2); + expect(stage.mask.type).toEqual(MASK_TYPES.COLOR); + expect(container1.mask.type).toEqual(MASK_TYPES.STENCIL); + expect(container2.mask.type).toEqual(MASK_TYPES.STENCIL); + expect(graphics.mask.type).toEqual(MASK_TYPES.COLOR); + expect(mask.mask.type).toEqual(MASK_TYPES.COLOR); - this.renderer.mask.pop(graphics2); + stage.destroy(true); - expect(maskData1.filter.maskSprite).to.equal(sprite1); + renderer.renderTexture.bind(renderTexture); - this.renderer.mask.pop(graphics1); + const pixels = new Uint8Array(8); + const gl = renderer.gl; - expect(maskData1.filter.maskSprite).to.be.null; - expect(maskData2.filter.maskSprite).to.be.null; + gl.readPixels(0, 0, 2, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); renderTexture.destroy(true); + + const [r1, g1, b1, a1, r2, g2, b2, a2] = pixels; + + // R B A + // G B A + // ------- + // G A + + expect(r1).toEqual(0x00); + expect(g1).toEqual(0x00); + expect(b1).toEqual(0x00); + expect(a1).toEqual(0x00); + expect(r2).toEqual(0x00); + expect(g2).toEqual(0xff); + expect(b2).toEqual(0x00); + expect(a2).toEqual(0xff); + }); + + it('should render overlapping objects with color masks correctly', () => + { + const stage = new Container(); + const graphics1 = new Graphics().beginFill(0xffffff, 1.0).drawRect(0, 0, 2, 1).endFill(); + const graphics2 = new Graphics().beginFill(0xffffff, 1.0).drawRect(1, 0, 2, 1).endFill(); + + stage.addChild(graphics1, graphics2); + + stage.mask = new MaskData(); + stage.mask.colorMask = COLOR_MASK_BITS.RED | COLOR_MASK_BITS.GREEN | COLOR_MASK_BITS.ALPHA; + graphics1.mask = new MaskData(); + graphics1.mask.colorMask = COLOR_MASK_BITS.RED | COLOR_MASK_BITS.BLUE | COLOR_MASK_BITS.ALPHA; + graphics2.mask = new MaskData(); + graphics2.mask.colorMask = COLOR_MASK_BITS.GREEN | COLOR_MASK_BITS.BLUE | COLOR_MASK_BITS.ALPHA; + + const renderTexture = renderer.generateTexture(stage); + + expect(renderTexture.width).toEqual(3); + expect(renderTexture.height).toEqual(1); + + expect(graphics1.mask.type).toEqual(MASK_TYPES.COLOR); + expect(graphics2.mask.type).toEqual(MASK_TYPES.COLOR); + + stage.destroy(true); + + renderer.renderTexture.bind(renderTexture); + + const pixels = new Uint8Array(12); + const gl = renderer.gl; + + gl.readPixels(0, 0, 3, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + + renderTexture.destroy(true); + + const [r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3] = pixels; + + expect(r1).toEqual(0xff); + expect(g1).toEqual(0x00); + expect(b1).toEqual(0x00); + expect(a1).toEqual(0xff); + expect(r2).toEqual(0xff); + expect(g2).toEqual(0xff); + expect(b2).toEqual(0x00); + expect(a2).toEqual(0xff); + expect(r3).toEqual(0x00); + expect(g3).toEqual(0xff); + expect(b3).toEqual(0x00); + expect(a3).toEqual(0xff); }); }); diff --git a/packages/core/test/ProjectionSystem.tests.ts b/packages/core/test/ProjectionSystem.tests.ts index a89c2664691..f713b271b1c 100644 --- a/packages/core/test/ProjectionSystem.tests.ts +++ b/packages/core/test/ProjectionSystem.tests.ts @@ -1,35 +1,36 @@ import { Renderer } from '@pixi/core'; import { Point, Rectangle } from '@pixi/math'; -import { expect } from 'chai'; -describe('ProjectionSystem', function () +describe('ProjectionSystem', () => { - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer = null; + renderer = null; }); - it('should calculate a projection-matrix that transforms a source-frame to the clipping rectangle', function () + it('should calculate a projection-matrix that transforms a source-frame to the clipping rectangle', () => { const sourceFrame = new Rectangle(16, 16, 1024, 1024); - this.renderer.projection.update(null, sourceFrame, 2, true); + renderer.projection.update(null, sourceFrame, 2, true); const sourceOrigin = new Point(16, 16); - const clipOrigin = this.renderer.projection.projectionMatrix.apply(sourceOrigin); + const clipOrigin = renderer.projection.projectionMatrix.apply(sourceOrigin); - expect(clipOrigin.x).to.equal(-1); - expect(clipOrigin.y).to.equal(1); + expect(clipOrigin.x).toEqual(-1); + expect(clipOrigin.y).toEqual(1); const sourceCorner = new Point(1040, 1040); - const clipCorner = this.renderer.projection.projectionMatrix.apply(sourceCorner); + const clipCorner = renderer.projection.projectionMatrix.apply(sourceCorner); - expect(clipCorner.x).to.equal(1); - expect(clipCorner.y).to.equal(-1); + expect(clipCorner.x).toEqual(1); + expect(clipCorner.y).toEqual(-1); }); }); diff --git a/packages/core/test/RenderTexture.tests.ts b/packages/core/test/RenderTexture.tests.ts index 8a17af513cb..c2599dd8f94 100644 --- a/packages/core/test/RenderTexture.tests.ts +++ b/packages/core/test/RenderTexture.tests.ts @@ -1,25 +1,25 @@ -import { RenderTexture, autoDetectRenderer, Framebuffer, Renderer, BatchRenderer } from '@pixi/core'; +import { RenderTexture, autoDetectRenderer, Framebuffer, Renderer } from '@pixi/core'; import { Graphics } from '@pixi/graphics'; import { Container } from '@pixi/display'; import { MSAA_QUALITY } from '@pixi/constants'; import { AlphaFilter } from '@pixi/filter-alpha'; -import { expect } from 'chai'; -describe('RenderTexture', function () +describe('RenderTexture', () => { - before(function () + let renderer: Renderer; + + beforeAll(() => { - Renderer.registerPlugin('batch', BatchRenderer); - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should destroy the depth texture too', function () + it('should destroy the depth texture too', () => { const renderer = autoDetectRenderer() as Renderer; @@ -33,14 +33,14 @@ describe('RenderTexture', function () renderer.renderTexture.bind(renderTexture); - expect(depthTexture._glTextures[renderer.CONTEXT_UID]).to.not.equal(undefined); + expect(depthTexture._glTextures[renderer.CONTEXT_UID]).not.toEqual(undefined); renderTexture.destroy(true); - expect(depthTexture._glTextures[renderer.CONTEXT_UID]).to.equal(undefined); + expect(depthTexture._glTextures[renderer.CONTEXT_UID]).toEqual(undefined); }); - it('should render correctly with empty mask', function () + it('should render correctly with empty mask', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 1, height: 1 }); @@ -59,23 +59,23 @@ describe('RenderTexture', function () container.addChild(graphics); container.mask = container.addChild(new Graphics()); - this.renderer.render(container, { renderTexture, clear: true }); + renderer.render(container, { renderTexture, clear: true }); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(51); - expect(pixel[1]).to.equal(51); - expect(pixel[2]).to.equal(51); - expect(pixel[3]).to.equal(51); + expect(pixel[0]).toEqual(51); + expect(pixel[1]).toEqual(51); + expect(pixel[2]).toEqual(51); + expect(pixel[3]).toEqual(51); }); - it('should render correctly with empty mask and multisampling', function () + it('should render correctly with empty mask and multisampling', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 1, height: 1 }); @@ -94,28 +94,28 @@ describe('RenderTexture', function () container.addChild(graphics); container.mask = container.addChild(new Graphics()); - this.renderer.render(container, { renderTexture, clear: true }); - this.renderer.framebuffer.blit(); + renderer.render(container, { renderTexture, clear: true }); + renderer.framebuffer.blit(); const textureFramebuffer = new Framebuffer(framebuffer.width, framebuffer.height); textureFramebuffer.addColorTexture(0, framebuffer.colorTextures[0]); - this.renderer.framebuffer.bind(textureFramebuffer); + renderer.framebuffer.bind(textureFramebuffer); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(51); - expect(pixel[1]).to.equal(51); - expect(pixel[2]).to.equal(51); - expect(pixel[3]).to.equal(51); + expect(pixel[0]).toEqual(51); + expect(pixel[1]).toEqual(51); + expect(pixel[2]).toEqual(51); + expect(pixel[3]).toEqual(51); }); - it('should render correctly with mask', function () + it('should render correctly with mask', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 2, height: 2 }); @@ -139,32 +139,32 @@ describe('RenderTexture', function () .endFill() ); - this.renderer.render(container, { renderTexture, clear: true }); + renderer.render(container, { renderTexture, clear: true }); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); pixel.set([0x80, 0x80, 0x80, 0x80]); gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(51); - expect(pixel[1]).to.equal(51); - expect(pixel[2]).to.equal(51); - expect(pixel[3]).to.equal(51); + expect(pixel[0]).toEqual(51); + expect(pixel[1]).toEqual(51); + expect(pixel[2]).toEqual(51); + expect(pixel[3]).toEqual(51); }); - it('should render correctly with stencil mask and filter', function () + it('should render correctly with stencil mask and filter', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 1, height: 1 }); @@ -186,27 +186,27 @@ describe('RenderTexture', function () container.mask = container.addChild( new Graphics() .beginFill(0xffffff) - .drawCircle(0, 0, 4, 4) + .drawCircle(0, 0, 4) .endFill() ); - this.renderer.render(container, { renderTexture, clear: true }); + renderer.render(container, { renderTexture, clear: true }); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); }); - it('should render correctly with mask and multisampling', function () + it('should render correctly with mask and multisampling', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 2, height: 2 }); @@ -230,37 +230,37 @@ describe('RenderTexture', function () .endFill() ); - this.renderer.render(container, { renderTexture, clear: true }); - this.renderer.framebuffer.blit(); + renderer.render(container, { renderTexture, clear: true }); + renderer.framebuffer.blit(); const textureFramebuffer = new Framebuffer(framebuffer.width, framebuffer.height); textureFramebuffer.addColorTexture(0, framebuffer.colorTextures[0]); - this.renderer.framebuffer.bind(textureFramebuffer); + renderer.framebuffer.bind(textureFramebuffer); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); pixel.set([0x80, 0x80, 0x80, 0x80]); gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(51); - expect(pixel[1]).to.equal(51); - expect(pixel[2]).to.equal(51); - expect(pixel[3]).to.equal(51); + expect(pixel[0]).toEqual(51); + expect(pixel[1]).toEqual(51); + expect(pixel[2]).toEqual(51); + expect(pixel[3]).toEqual(51); }); - it('should resize framebuffer', function () + it('should resize framebuffer', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 1, height: 1 }); @@ -274,27 +274,27 @@ describe('RenderTexture', function () graphics.beginFill(0xffffff).drawRect(0, 0, 2, 2).endFill(); - this.renderer.render(graphics, { renderTexture, clear: true }); + renderer.render(graphics, { renderTexture, clear: true }); renderTexture.resize(2, 2); - this.renderer.render(graphics, { renderTexture, clear: true }); + renderer.render(graphics, { renderTexture, clear: true }); - this.renderer.renderTexture.bind(renderTexture); + renderer.renderTexture.bind(renderTexture); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); }); - it('should resize multisampled framebuffer', function () + it('should resize multisampled framebuffer', () => { - const { gl } = this.renderer; + const { gl } = renderer; const renderTexture = RenderTexture.create({ width: 1, height: 1 }); @@ -308,27 +308,27 @@ describe('RenderTexture', function () graphics.beginFill(0xffffff).drawRect(0, 0, 2, 2).endFill(); - this.renderer.render(graphics, { renderTexture, clear: true }); - this.renderer.framebuffer.blit(); + renderer.render(graphics, { renderTexture, clear: true }); + renderer.framebuffer.blit(); renderTexture.resize(2, 2); - this.renderer.render(graphics, { renderTexture, clear: true }); - this.renderer.framebuffer.blit(); + renderer.render(graphics, { renderTexture, clear: true }); + renderer.framebuffer.blit(); const textureFramebuffer = new Framebuffer(framebuffer.width, framebuffer.height); textureFramebuffer.addColorTexture(0, framebuffer.colorTextures[0]); - this.renderer.framebuffer.bind(textureFramebuffer); + renderer.framebuffer.bind(textureFramebuffer); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); }); }); diff --git a/packages/core/test/RenderTexturePool.tests.ts b/packages/core/test/RenderTexturePool.tests.ts index 9e787540eff..f7fd65f0dc6 100644 --- a/packages/core/test/RenderTexturePool.tests.ts +++ b/packages/core/test/RenderTexturePool.tests.ts @@ -1,36 +1,35 @@ import { RenderTexturePool } from '@pixi/core'; -import { expect } from 'chai'; -describe('RenderTexturePool', function () +describe('RenderTexturePool', () => { - it('should destroy screen-sized textures on resize', function () + it('should destroy screen-sized textures on resize', () => { const renderTexturePool = new RenderTexturePool(); renderTexturePool.setScreenSize({ width: 100, height: 100 }); - expect(renderTexturePool.enableFullScreen).to.be.true; + expect(renderTexturePool.enableFullScreen).toBe(true); const renderTexture = renderTexturePool.getOptimalTexture(100, 100); const baseRenderTexture = renderTexture.baseTexture; - expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).to.equal(0); + expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).toEqual(0); renderTexturePool.returnTexture(renderTexture); - expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).to.equal(1); + expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).toEqual(1); renderTexturePool.setScreenSize({ width: 50, height: 50 }); - expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).to.equal(0); + expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).toEqual(0); - expect(renderTexture.baseTexture).to.be.null; - expect(baseRenderTexture.destroyed).to.be.true; + expect(renderTexture.baseTexture).toBeNull(); + expect(baseRenderTexture.destroyed).toBe(true); renderTexturePool.clear(true); }); - it('should create screen-sized texture with noninteger resolution', function () + it('should create screen-sized texture with noninteger resolution', () => { const resolution = 1.1; const viewWidth = 1419; @@ -38,27 +37,27 @@ describe('RenderTexturePool', function () const screenWidth = viewWidth / resolution; const screenHeight = viewHeight / resolution; - expect(screenWidth * resolution).to.equal(1419.0000000000002); - expect(screenHeight * resolution).to.equal(982.9999999999999); + expect(screenWidth * resolution).toEqual(1419.0000000000002); + expect(screenHeight * resolution).toEqual(982.9999999999999); const renderTexturePool = new RenderTexturePool(); renderTexturePool.setScreenSize({ width: viewWidth, height: viewHeight }); - expect(renderTexturePool.enableFullScreen).to.be.true; + expect(renderTexturePool.enableFullScreen).toBe(true); const renderTexture = renderTexturePool.getOptimalTexture(screenWidth, screenHeight, resolution); const baseRenderTexture = renderTexture.baseTexture; - expect(baseRenderTexture.width).to.equal(screenWidth); - expect(baseRenderTexture.height).to.equal(screenHeight); - expect(baseRenderTexture.realWidth).to.equal(viewWidth); - expect(baseRenderTexture.realHeight).to.equal(viewHeight); - expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).to.equal(0); + expect(baseRenderTexture.width).toEqual(screenWidth); + expect(baseRenderTexture.height).toEqual(screenHeight); + expect(baseRenderTexture.realWidth).toEqual(viewWidth); + expect(baseRenderTexture.realHeight).toEqual(viewHeight); + expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).toEqual(0); renderTexturePool.returnTexture(renderTexture); - expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).to.equal(1); + expect(renderTexturePool.texturePool[RenderTexturePool.SCREEN_KEY]?.length ?? 0).toEqual(1); renderTexturePool.clear(true); }); diff --git a/packages/core/test/RenderTextureSystem.tests.ts b/packages/core/test/RenderTextureSystem.tests.ts index 0271784b180..8a1a9756637 100644 --- a/packages/core/test/RenderTextureSystem.tests.ts +++ b/packages/core/test/RenderTextureSystem.tests.ts @@ -1,55 +1,56 @@ import { Renderer } from '@pixi/core'; import { Rectangle } from '@pixi/math'; -import { expect } from 'chai'; -describe('RenderTextureSystem', function () +describe('RenderTextureSystem', () => { - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer({ resolution: 4, width: 1024, height: 1024 }); + renderer = new Renderer({ resolution: 4, width: 1024, height: 1024 }); }); - after(function () + afterAll(() => { - this.renderer = null; + renderer = null; }); - it('the default viewport should have a width/height equal to that of the renderer', function () + it('the default viewport should have a width/height equal to that of the renderer', () => { - this.renderer.renderTexture.bind(); + renderer.renderTexture.bind(); - const viewport = this.renderer.framebuffer.viewport; + const viewport = renderer.framebuffer.viewport; - expect(viewport.x).to.equal(0); - expect(viewport.y).to.equal(0); - expect(viewport.width).to.equal(this.renderer.width); - expect(viewport.height).to.equal(this.renderer.height); + expect(viewport.x).toEqual(0); + expect(viewport.y).toEqual(0); + expect(viewport.width).toEqual(renderer.width); + expect(viewport.height).toEqual(renderer.height); - const destinationFrame = this.renderer.renderTexture.destinationFrame; + const destinationFrame = renderer.renderTexture.destinationFrame; - expect(destinationFrame.x).to.equal(0); - expect(destinationFrame.y).to.equal(0); - expect(destinationFrame.width).to.equal(this.renderer.width / this.renderer.resolution); - expect(destinationFrame.height).to.equal(this.renderer.height / this.renderer.resolution); + expect(destinationFrame.x).toEqual(0); + expect(destinationFrame.y).toEqual(0); + expect(destinationFrame.width).toEqual(renderer.width / renderer.resolution); + expect(destinationFrame.height).toEqual(renderer.height / renderer.resolution); }); - it('rebinding with the same source & destination frame should change nothing', function () + it('rebinding with the same source & destination frame should change nothing', () => { const sourceFrame = new Rectangle(16, 16, 512, 512); const destinationFrame = new Rectangle(24, 24, 64, 64); - const renderTextureSystem = this.renderer.renderTexture; + const renderTextureSystem = renderer.renderTexture; renderTextureSystem.bind(null, sourceFrame, destinationFrame); renderTextureSystem.bind(null, renderTextureSystem.sourceFrame, renderTextureSystem.destinationFrame); - expect(destinationFrame.x).to.equal(renderTextureSystem.destinationFrame.x); - expect(destinationFrame.y).to.equal(renderTextureSystem.destinationFrame.y); - expect(destinationFrame.width).to.equal(renderTextureSystem.destinationFrame.width); - expect(destinationFrame.height).to.equal(renderTextureSystem.destinationFrame.height); + expect(destinationFrame.x).toEqual(renderTextureSystem.destinationFrame.x); + expect(destinationFrame.y).toEqual(renderTextureSystem.destinationFrame.y); + expect(destinationFrame.width).toEqual(renderTextureSystem.destinationFrame.width); + expect(destinationFrame.height).toEqual(renderTextureSystem.destinationFrame.height); - expect(sourceFrame.x).to.equal(renderTextureSystem.sourceFrame.x); - expect(sourceFrame.y).to.equal(renderTextureSystem.sourceFrame.y); - expect(sourceFrame.width).to.equal(renderTextureSystem.sourceFrame.width); - expect(sourceFrame.height).to.equal(renderTextureSystem.sourceFrame.height); + expect(sourceFrame.x).toEqual(renderTextureSystem.sourceFrame.x); + expect(sourceFrame.y).toEqual(renderTextureSystem.sourceFrame.y); + expect(sourceFrame.width).toEqual(renderTextureSystem.sourceFrame.width); + expect(sourceFrame.height).toEqual(renderTextureSystem.sourceFrame.height); }); }); diff --git a/packages/core/test/Renderer.tests.ts b/packages/core/test/Renderer.tests.ts index f3385b80b5d..850b8737590 100644 --- a/packages/core/test/Renderer.tests.ts +++ b/packages/core/test/Renderer.tests.ts @@ -1,24 +1,22 @@ +import type { ObjectRenderer } from '@pixi/core'; import { Renderer, Framebuffer } from '@pixi/core'; import { Graphics } from '@pixi/graphics'; import { settings } from '@pixi/settings'; import { ENV, MSAA_QUALITY } from '@pixi/constants'; import { skipHello } from '@pixi/utils'; -import sinon from 'sinon'; -import { expect } from 'chai'; skipHello(); -describe('Renderer', function () +describe('Renderer', () => { - it('setting option legacy should disable VAOs and SPRITE_MAX_TEXTURES', function () + it('setting option legacy should disable VAOs and SPRITE_MAX_TEXTURES', () => { settings.PREFER_ENV = ENV.WEBGL_LEGACY; const renderer = new Renderer({ width: 1, height: 1 }); try { - expect(renderer.geometry.hasVao).to.equal(false); - // expect(renderer.plugins.sprite.MAX_TEXTURES).to.equal(1); + expect(renderer.geometry.hasVao).toEqual(false); } finally { @@ -27,7 +25,7 @@ describe('Renderer', function () settings.PREFER_ENV = ENV.WEBGL2; }); - it('should allow clear() to work despite no containers added to the renderer', function () + it('should allow clear() to work despite no containers added to the renderer', () => { const renderer = new Renderer({ width: 1, height: 1 }); @@ -41,74 +39,77 @@ describe('Renderer', function () } }); - it('should emit resize event', function () + it('should emit resize event', () => { const renderer = new Renderer({ width: 1, height: 1 }); - const spy = sinon.spy(); + const spy = jest.fn(); renderer.on('resize', spy); renderer.resize(2, 4); - expect(spy.calledOnce).to.be.true; - expect(spy.firstCall.args[0]).to.equal(2); - expect(spy.firstCall.args[1]).to.equal(4); + expect(spy).toBeCalledTimes(1); + expect(spy).toHaveBeenCalledWith(2, 4); renderer.destroy(); }); - describe('.setObjectRenderer()', function () + describe('.setObjectRenderer()', () => { - before(function () + let renderer: Renderer; + let curRenderer: ObjectRenderer; + let objRenderer: ObjectRenderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - beforeEach(function () + beforeEach(() => { - this.curRenderer = { - start: sinon.spy(), - stop: sinon.spy(), - }; - this.objRenderer = { - start: sinon.spy(), - stop: sinon.spy(), - }; - this.renderer.batch.currentRenderer = this.curRenderer; + curRenderer = { + start: jest.fn(), + stop: jest.fn(), + } as unknown as ObjectRenderer; + objRenderer = { + start: jest.fn(), + stop: jest.fn(), + } as unknown as ObjectRenderer; + renderer.batch.currentRenderer = curRenderer; }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; - this.curRenderer = null; - this.objRenderer = null; + renderer.destroy(); + renderer = null; + curRenderer = null; + objRenderer = null; }); - it('should set objectRenderer as new current renderer', function () + it('should set objectRenderer as new current renderer', () => { - this.renderer.batch.setObjectRenderer(this.objRenderer); - expect(this.curRenderer.stop).to.be.calledOnce; - expect(this.renderer.batch.currentRenderer).to.be.equal(this.objRenderer); - expect(this.objRenderer.start).to.be.calledOnce; + renderer.batch.setObjectRenderer(objRenderer); + expect(curRenderer.stop).toHaveBeenCalledOnce(); + expect(renderer.batch.currentRenderer).toEqual(objRenderer); + expect(objRenderer.start).toHaveBeenCalledOnce(); }); - it('should do nothing if objectRenderer is already used as current', function () + it('should do nothing if objectRenderer is already used as current', () => { - this.renderer.batch.setObjectRenderer(this.curRenderer); - expect(this.renderer.batch.currentRenderer).to.be.equal(this.curRenderer); - expect(this.curRenderer.stop).to.not.be.called; - expect(this.curRenderer.start).to.not.be.called; + renderer.batch.setObjectRenderer(curRenderer); + expect(renderer.batch.currentRenderer).toEqual(curRenderer); + expect(curRenderer.stop).not.toBeCalled(); + expect(curRenderer.start).not.toBeCalled(); }); - it('should generate a multisampled texture', function () + it('should generate a multisampled texture', () => { - const { gl } = this.renderer; + const { gl } = renderer; const graphics = new Graphics(); graphics.beginFill(0xffffff).drawRect(0, 0, 1, 1).endFill(); - const renderTexture = this.renderer.generateTexture(graphics, { multisample: MSAA_QUALITY.HIGH }); + const renderTexture = renderer.generateTexture(graphics, { multisample: MSAA_QUALITY.HIGH }); const framebuffer = renderTexture.framebuffer; @@ -116,16 +117,16 @@ describe('Renderer', function () textureFramebuffer.addColorTexture(0, framebuffer.colorTextures[0]); - this.renderer.framebuffer.bind(textureFramebuffer); + renderer.framebuffer.bind(textureFramebuffer); const pixel = new Uint8Array([0x80, 0x80, 0x80, 0x80]); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); - expect(pixel[0]).to.equal(0xff); - expect(pixel[1]).to.equal(0xff); - expect(pixel[2]).to.equal(0xff); - expect(pixel[3]).to.equal(0xff); + expect(pixel[0]).toEqual(0xff); + expect(pixel[1]).toEqual(0xff); + expect(pixel[2]).toEqual(0xff); + expect(pixel[3]).toEqual(0xff); }); }); }); diff --git a/packages/core/test/SVGResource.tests.ts b/packages/core/test/SVGResource.tests.ts index e64deda431a..c12f9372d46 100644 --- a/packages/core/test/SVGResource.tests.ts +++ b/packages/core/test/SVGResource.tests.ts @@ -1,111 +1,112 @@ import { SVGResource } from '@pixi/core'; import fs from 'fs'; import path from 'path'; -import { expect } from 'chai'; -describe('SVGResource', function () +describe('SVGResource', () => { - before(function () + let resources: string; + + beforeAll(() => { - this.resources = path.join(__dirname, 'resources'); + resources = path.join(__dirname, 'resources'); }); - describe('constructor', function () + describe('constructor', () => { - it('should create new resource from data-uri', function (done) + it('should create new resource from data-uri', (done) => { - const url = path.join(this.resources, 'svg-base64.txt'); + const url = path.join(resources, 'svg-base64.txt'); const buffer = fs.readFileSync(url, 'utf8'); const resource = new SVGResource(buffer, { autoLoad: false }); - expect(resource.valid).to.equal(false); - resource.load().then(function () + expect(resource.valid).toEqual(false); + resource.load().then(() => { - expect(resource.valid).to.equal(true); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); + expect(resource.valid).toEqual(true); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); done(); }); }); - it('should create new resource from data-uri with charset=utf8', function (done) + it('should create new resource from data-uri with charset=utf8', (done) => { - const url = path.join(this.resources, 'svg-base64-utf8.txt'); + const url = path.join(resources, 'svg-base64-utf8.txt'); const buffer = fs.readFileSync(url, 'utf8'); const resource = new SVGResource(buffer, { autoLoad: false }); - expect(resource.valid).to.equal(false); - resource.load().then(function () + expect(resource.valid).toEqual(false); + resource.load().then(() => { - expect(resource.valid).to.equal(true); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); + expect(resource.valid).toEqual(true); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); done(); }); }); - it('should create resource from SVG URL', function (done) + it('should create resource from SVG URL', (done) => { const resource = new SVGResource( - path.join(this.resources, 'heart.svg'), + path.join(resources, 'heart.svg'), { autoLoad: false } ); - expect(resource.valid).to.equal(false); - resource.load().then(function () + expect(resource.valid).toEqual(false); + resource.load().then(() => { - expect(resource.valid).to.equal(true); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); + expect(resource.valid).toEqual(true); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); done(); }); }); - it('should create resource from SVG URL with {scale: 2.123}', function (done) + it('should create resource from SVG URL with {scale: 2.123}', (done) => { const resource = new SVGResource( - path.join(this.resources, 'heart.svg'), + path.join(resources, 'heart.svg'), { autoLoad: false, scale: 2.123, } ); - resource.load().then(function () + resource.load().then(() => { - expect(resource.width).to.equal(212); - expect(resource.height).to.equal(212); + expect(resource.width).toEqual(212); + expect(resource.height).toEqual(212); done(); }); }); - it('should create resource from SVG URL with {width: 10}', function (done) + it('should create resource from SVG URL with {width: 10}', (done) => { const resource = new SVGResource( - path.join(this.resources, 'heart.svg'), + path.join(resources, 'heart.svg'), { autoLoad: false, width: 10, } ); - resource.load().then(function () + resource.load().then(() => { - expect(resource.width).to.equal(10); - expect(resource.height).to.equal(10); + expect(resource.width).toEqual(10); + expect(resource.height).toEqual(10); done(); }); }); - it('should create resource from SVG URL with {width: 10, height: 10}', function (done) + it('should create resource from SVG URL with {width: 10, height: 10}', (done) => { const resource = new SVGResource( - path.join(this.resources, 'heart.svg'), + path.join(resources, 'heart.svg'), { autoLoad: false, width: 10, @@ -113,114 +114,114 @@ describe('SVGResource', function () } ); - resource.load().then(function () + resource.load().then(() => { - expect(resource.width).to.equal(10); - expect(resource.height).to.equal(10); + expect(resource.width).toEqual(10); + expect(resource.height).toEqual(10); done(); }); }); - it('should create resource from inline SVG', function (done) + it('should create resource from inline SVG', (done) => { - const url = path.join(this.resources, 'heart.svg'); + const url = path.join(resources, 'heart.svg'); const buffer = fs.readFileSync(url, 'utf8'); const resource = new SVGResource(buffer, { autoLoad: false }); - expect(resource.valid).to.equal(false); - resource.load().then(function () + expect(resource.valid).toEqual(false); + resource.load().then(() => { - expect(resource.valid).to.equal(true); - expect(resource.width).to.equal(100); - expect(resource.height).to.equal(100); + expect(resource.valid).toEqual(true); + expect(resource.width).toEqual(100); + expect(resource.height).toEqual(100); done(); }); }); - it('should create resource from SVG with XML Prolog', function (done) + it('should create resource from SVG with XML Prolog', (done) => { - const url = path.join(this.resources, 'circle-with-prolog.svg'); + const url = path.join(resources, 'circle-with-prolog.svg'); const buffer = fs.readFileSync(url, 'utf8'); const resource = new SVGResource(buffer, { autoLoad: false }); - expect(buffer.startsWith(' { - expect(resource.valid).to.equal(true); - expect(resource.width).to.equal(48); - expect(resource.height).to.equal(48); + expect(resource.valid).toEqual(true); + expect(resource.width).toEqual(48); + expect(resource.height).toEqual(48); done(); }); }); }); - describe('getSize', function () + describe('getSize', () => { - it('should exist', function () + it('should exist', () => { expect(SVGResource.getSize) - .to.be.a('function'); + .toBeInstanceOf(Function); }); - it('should return a size object with width and height from an SVG string', function () + it('should return a size object with width and height from an SVG string', () => { const svgSize = SVGResource.getSize(''); expect(svgSize) - .to.be.an('object'); + .toBeObject(); expect(svgSize.width) - .to.equal(64); + .toEqual(64); expect(svgSize.height) - .to.equal(32); + .toEqual(32); }); - it('should return a size object from an SVG string with inverted quotes', function () + it('should return a size object from an SVG string with inverted quotes', () => { - const svgSize = SVGResource.getSize(""); // eslint-disable-line quotes + const svgSize = SVGResource.getSize(''); // eslint-disable-line quotes expect(svgSize) - .to.be.an('object'); + .toBeObject(); expect(svgSize.width) - .to.equal(64); + .toEqual(64); expect(svgSize.height) - .to.equal(32); + .toEqual(32); }); - it('should work with px values', function () + it('should work with px values', () => { const svgSize = SVGResource.getSize(''); expect(svgSize) - .to.be.an('object'); + .toBeObject(); expect(svgSize.width) - .to.equal(64); + .toEqual(64); expect(svgSize.height) - .to.equal(32); + .toEqual(32); }); - it('should return an empty object when width and/or height is missing', function () + it('should return an empty object when width and/or height is missing', () => { const svgSize = SVGResource.getSize(''); expect(Object.keys(svgSize).length) - .to.equal(0); + .toEqual(0); }); }); - describe('test', function () + describe('test', () => { - it('should pass simple SVG document', function () + it('should pass simple SVG document', () => { const didPass = SVGResource.test(``, 'xml'); - expect(didPass).to.equal(true); + expect(didPass).toEqual(true); }); - it('should pass SVG document with prolog', function () + it('should pass SVG document with prolog', () => { const didPass = SVGResource.test(` @@ -228,25 +229,25 @@ describe('SVGResource', function () Hello world `, 'xml'); - expect(didPass).to.equal(true); + expect(didPass).toEqual(true); }); - it('should pass SVG document with only prolog, no comments', function () + it('should pass SVG document with only prolog, no comments', () => { const didPass = SVGResource.test( `Hello world`, 'xml'); - expect(didPass).to.equal(true); + expect(didPass).toEqual(true); }); - it('should not pass HTML fragment', function () + it('should not pass HTML fragment', () => { const didPass = SVGResource.test( `This is a mistake`, 'xml'); - expect(didPass).to.equal(false); + expect(didPass).toEqual(false); }); }); }); diff --git a/packages/core/test/Shader.tests.ts b/packages/core/test/Shader.tests.ts index 8e64c4d3bde..487dbdbcf89 100644 --- a/packages/core/test/Shader.tests.ts +++ b/packages/core/test/Shader.tests.ts @@ -3,7 +3,7 @@ import { skipHello } from '@pixi/utils'; skipHello(); -describe('Shader', function () +describe('Shader', () => { const vertexSrc = ` attribute vec2 aVertexPosition; @@ -14,20 +14,23 @@ void main() { }`; - before(function () + let renderer: Renderer; + let geometry: Geometry; + + beforeAll(() => { - this.renderer = new Renderer(); - this.geometry = new Geometry() + renderer = new Renderer(); + geometry = new Geometry() .addAttribute('aVertexPosition', [-100, -100, 100, -100, 100, 100], 2); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should be able to set uniform value', function () + it('should be able to set uniform value', () => { const fragmentSrc = ` uniform float uTestFloat; @@ -42,11 +45,11 @@ void main() { shader.uniforms.uTestFloat = 0.88; - this.renderer.shader.bind(shader); - this.renderer.geometry.bind(this.geometry); + renderer.shader.bind(shader); + renderer.geometry.bind(geometry); }); - it('should be able to set uniform arrays', function () + it('should be able to set uniform arrays', () => { const fragmentSrc = ` uniform float uTestFloat[3]; @@ -61,11 +64,11 @@ void main() { shader.uniforms.uTestFloat = [1, 2, 3]; - this.renderer.shader.bind(shader); - this.renderer.geometry.bind(this.geometry); + renderer.shader.bind(shader); + renderer.geometry.bind(geometry); }); - it('should be able to set uniform structs', function () + it('should be able to set uniform structs', () => { const fragmentSrc = ` struct Test { @@ -84,11 +87,11 @@ void main() { shader.uniforms['uTest.testFloat'] = 1; - this.renderer.shader.bind(shader); - this.renderer.geometry.bind(this.geometry); + renderer.shader.bind(shader); + renderer.geometry.bind(geometry); }); - it('should be able to set uniform struct arrays', function () + it('should be able to set uniform struct arrays', () => { const fragmentSrc = ` struct Test { @@ -119,7 +122,7 @@ void main() { shader.uniforms['uTest[2].testFloat'] = 3.3; shader.uniforms['uTest[2].testVec3'] = [1, 2, 3]; - this.renderer.shader.bind(shader); - this.renderer.geometry.bind(this.geometry); + renderer.shader.bind(shader); + renderer.geometry.bind(geometry); }); }); diff --git a/packages/core/test/ShaderSystem.tests.ts b/packages/core/test/ShaderSystem.tests.ts index 396a4d26f2c..2200e4eaba3 100644 --- a/packages/core/test/ShaderSystem.tests.ts +++ b/packages/core/test/ShaderSystem.tests.ts @@ -1,10 +1,9 @@ import { Renderer, Shader, CanvasResource, Geometry, UniformGroup, BaseTexture } from '@pixi/core'; import { skipHello } from '@pixi/utils'; -import { expect } from 'chai'; skipHello(); -describe('ShaderSystem', function () +describe('ShaderSystem', () => { const vertexSrc = ` attribute vec2 aVertexPosition; @@ -34,7 +33,7 @@ void main() { }`; - function createTexture(w, h) + function createTexture(w: number, h: number) { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); @@ -47,20 +46,21 @@ void main() { return new BaseTexture(new CanvasResource(canvas)); } - before(function () + let renderer: Renderer; + + beforeAll(() => { - this.renderer = new Renderer(); + renderer = new Renderer(); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should set textures in different groups to different locations', function () + it('should set textures in different groups to different locations', () => { - const renderer = this.renderer; const texture1 = createTexture(10, 10); const texture2 = createTexture(20, 20); @@ -74,7 +74,7 @@ void main() { renderer.shader.bind(shader); renderer.geometry.bind(geometry); // actually, order is not important. But if behaviour changes, we'll be better knowing about that - expect(renderer.texture.boundTextures[0]).to.equal(texture2); - expect(renderer.texture.boundTextures[1]).to.equal(texture1); + expect(renderer.texture.boundTextures[0]).toEqual(texture2); + expect(renderer.texture.boundTextures[1]).toEqual(texture1); }); }); diff --git a/packages/core/test/Texture.tests.ts b/packages/core/test/Texture.tests.ts index e376c048f4f..5395933ff2c 100644 --- a/packages/core/test/Texture.tests.ts +++ b/packages/core/test/Texture.tests.ts @@ -1,8 +1,10 @@ import { BaseTextureCache, TextureCache } from '@pixi/utils'; import { Rectangle, Point } from '@pixi/math'; +import type { ImageResource } from '@pixi/core'; import { BaseTexture, Texture } from '@pixi/core'; import { settings } from '@pixi/settings'; -import { expect } from 'chai'; + +import path from 'path'; const URL = 'foo.png'; const NAME = 'foo'; @@ -19,9 +21,14 @@ function cleanCache() delete TextureCache[NAME2]; } -describe('Texture', function () +interface PixiCanvas extends HTMLCanvasElement { - it('should register Texture from Loader', function (done) + _pixiId: string; +} + +describe('Texture', () => +{ + it('should register Texture from Loader', (done) => { cleanCache(); @@ -32,17 +39,17 @@ describe('Texture', function () Texture.fromLoader(image, URL, NAME).then((texture) => { - expect(texture.baseTexture.resource.url).to.equal('foo.png'); - expect(TextureCache[NAME]).to.equal(texture); - expect(BaseTextureCache[NAME]).to.equal(texture.baseTexture); - expect(TextureCache[URL]).to.equal(texture); - expect(BaseTextureCache[URL]).to.equal(texture.baseTexture); + expect((texture.baseTexture.resource as ImageResource).url).toEqual('foo.png'); + expect(TextureCache[NAME]).toEqual(texture); + expect(BaseTextureCache[NAME]).toEqual(texture.baseTexture); + expect(TextureCache[URL]).toEqual(texture); + expect(BaseTextureCache[URL]).toEqual(texture.baseTexture); done(); }); }); - it('should remove Texture from cache on destroy', function () + it('should remove Texture from cache on destroy', () => { cleanCache(); @@ -50,34 +57,34 @@ describe('Texture', function () Texture.addToCache(texture, NAME); Texture.addToCache(texture, NAME2); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.textureCacheIds.indexOf(NAME2)).to.equal(1); - expect(TextureCache[NAME]).to.equal(texture); - expect(TextureCache[NAME2]).to.equal(texture); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.textureCacheIds.indexOf(NAME2)).toEqual(1); + expect(TextureCache[NAME]).toEqual(texture); + expect(TextureCache[NAME2]).toEqual(texture); texture.destroy(); - expect(texture.textureCacheIds).to.equal(null); - expect(TextureCache[NAME]).to.equal(undefined); - expect(TextureCache[NAME2]).to.equal(undefined); + expect(texture.textureCacheIds).toEqual(null); + expect(TextureCache[NAME]).toEqual(undefined); + expect(TextureCache[NAME2]).toEqual(undefined); }); - it('should use pixiIdPrefix correctly', function () + it('should use pixiIdPrefix correctly', () => { cleanCache(); const canvas = document.createElement('canvas'); const texture = Texture.from(canvas, { pixiIdPrefix: 'unittest' }); - const baseTexture = texture.baseTexture; - const _pixiId = baseTexture.resource.source._pixiId; - - expect(_pixiId.indexOf('unittest_')).to.equal(0); - expect(baseTexture.textureCacheIds.indexOf(_pixiId)).to.equal(0); - expect(BaseTextureCache[_pixiId]).to.equal(baseTexture); - expect(texture.textureCacheIds.indexOf(_pixiId)).to.equal(0); - expect(TextureCache[_pixiId]).to.equal(texture); + const baseTexture = texture.baseTexture as BaseTexture; + const _pixiId = (baseTexture.resource.source as PixiCanvas)._pixiId; + + expect(_pixiId.indexOf('unittest_')).toEqual(0); + expect(baseTexture.textureCacheIds.indexOf(_pixiId)).toEqual(0); + expect(BaseTextureCache[_pixiId]).toEqual(baseTexture); + expect(texture.textureCacheIds.indexOf(_pixiId)).toEqual(0); + expect(TextureCache[_pixiId]).toEqual(texture); }); it('should be added to the texture cache correctly, ' - + 'and should remove only itself, not effecting the base texture and its cache', function () + + 'and should remove only itself, not effecting the base texture and its cache', () => { cleanCache(); @@ -85,18 +92,18 @@ describe('Texture', function () BaseTexture.addToCache(texture.baseTexture, NAME); Texture.addToCache(texture, NAME); - expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(BaseTextureCache[NAME]).to.equal(texture.baseTexture); - expect(TextureCache[NAME]).to.equal(texture); + expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(BaseTextureCache[NAME]).toEqual(texture.baseTexture); + expect(TextureCache[NAME]).toEqual(texture); Texture.removeFromCache(NAME); - expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(BaseTextureCache[NAME]).to.equal(texture.baseTexture); - expect(TextureCache[NAME]).to.equal(undefined); + expect(texture.baseTexture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(BaseTextureCache[NAME]).toEqual(texture.baseTexture); + expect(TextureCache[NAME]).toEqual(undefined); }); - it('should remove Texture from entire cache using removeFromCache (by Texture instance)', function () + it('should remove Texture from entire cache using removeFromCache (by Texture instance)', () => { cleanCache(); @@ -104,18 +111,18 @@ describe('Texture', function () Texture.addToCache(texture, NAME); Texture.addToCache(texture, NAME2); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.textureCacheIds.indexOf(NAME2)).to.equal(1); - expect(TextureCache[NAME]).to.equal(texture); - expect(TextureCache[NAME2]).to.equal(texture); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.textureCacheIds.indexOf(NAME2)).toEqual(1); + expect(TextureCache[NAME]).toEqual(texture); + expect(TextureCache[NAME2]).toEqual(texture); Texture.removeFromCache(texture); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(texture.textureCacheIds.indexOf(NAME2)).to.equal(-1); - expect(TextureCache[NAME]).to.equal(undefined); - expect(TextureCache[NAME2]).to.equal(undefined); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(texture.textureCacheIds.indexOf(NAME2)).toEqual(-1); + expect(TextureCache[NAME]).toEqual(undefined); + expect(TextureCache[NAME2]).toEqual(undefined); }); - it('should remove Texture from single cache entry using removeFromCache (by id)', function () + it('should remove Texture from single cache entry using removeFromCache (by id)', () => { cleanCache(); @@ -123,18 +130,18 @@ describe('Texture', function () Texture.addToCache(texture, NAME); Texture.addToCache(texture, NAME2); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(texture.textureCacheIds.indexOf(NAME2)).to.equal(1); - expect(TextureCache[NAME]).to.equal(texture); - expect(TextureCache[NAME2]).to.equal(texture); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(texture.textureCacheIds.indexOf(NAME2)).toEqual(1); + expect(TextureCache[NAME]).toEqual(texture); + expect(TextureCache[NAME2]).toEqual(texture); Texture.removeFromCache(NAME); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(texture.textureCacheIds.indexOf(NAME2)).to.equal(0); - expect(TextureCache[NAME]).to.equal(undefined); - expect(TextureCache[NAME2]).to.equal(texture); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(texture.textureCacheIds.indexOf(NAME2)).toEqual(0); + expect(TextureCache[NAME]).toEqual(undefined); + expect(TextureCache[NAME2]).toEqual(texture); }); - it('should not remove Texture from cache if Texture instance has been replaced', function () + it('should not remove Texture from cache if Texture instance has been replaced', () => { cleanCache(); @@ -142,18 +149,18 @@ describe('Texture', function () const texture2 = new Texture(new BaseTexture()); Texture.addToCache(texture, NAME); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(TextureCache[NAME]).to.equal(texture); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(TextureCache[NAME]).toEqual(texture); Texture.addToCache(texture2, NAME); - expect(texture2.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(TextureCache[NAME]).to.equal(texture2); + expect(texture2.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(TextureCache[NAME]).toEqual(texture2); Texture.removeFromCache(texture); - expect(texture.textureCacheIds.indexOf(NAME)).to.equal(-1); - expect(texture2.textureCacheIds.indexOf(NAME)).to.equal(0); - expect(TextureCache[NAME]).to.equal(texture2); + expect(texture.textureCacheIds.indexOf(NAME)).toEqual(-1); + expect(texture2.textureCacheIds.indexOf(NAME)).toEqual(0); + expect(TextureCache[NAME]).toEqual(texture2); }); - it('destroying a destroyed texture should not throw an error', function () + it('destroying a destroyed texture should not throw an error', () => { const texture = new Texture(new BaseTexture()); @@ -161,7 +168,7 @@ describe('Texture', function () texture.destroy(true); }); - it('should not throw if base texture loaded after destroy', function () + it('should not throw if base texture loaded after destroy', () => { const base = new BaseTexture(); const texture = new Texture(base); @@ -170,28 +177,28 @@ describe('Texture', function () base.emit('loaded', base); }); - it('should clone a minimal texture', function () + it('should clone a minimal texture', () => { const baseTexture = new BaseTexture(); const frame = new Rectangle(0, 0, 10, 10); const texture = new Texture(baseTexture, frame); const clone = texture.clone(); - const toJSON = ({ x, y, width, height }) => ({ x, y, width, height }); + const toJSON = ({ x, y, width, height }: any) => ({ x, y, width, height }); - expect(clone.baseTexture).to.equal(baseTexture); - expect(clone.frame).to.not.equal(texture.frame); - expect(toJSON(clone.frame)).to.deep.equal(toJSON(texture.frame)); - expect(clone.trim).to.be.undefined; - expect(clone.orig).to.not.equal(texture.orig); - expect(toJSON(clone.orig)).to.deep.equal(toJSON(texture.orig)); - expect(clone.frame === clone.orig).to.equal(texture.frame === texture.orig); - expect(clone.noFrame).to.equal(texture.noFrame); + expect(clone.baseTexture).toEqual(baseTexture); + expect(clone.frame).not.toBe(texture.frame); + expect(toJSON(clone.frame)).toEqual(toJSON(texture.frame)); + expect(clone.trim).toBeUndefined(); + expect(clone.orig).not.toBe(texture.orig); + expect(toJSON(clone.orig)).toEqual(toJSON(texture.orig)); + expect(clone.frame === clone.orig).toEqual(texture.frame === texture.orig); + expect(clone.noFrame).toEqual(texture.noFrame); clone.destroy(); texture.destroy(true); }); - it('should clone a texture', function () + it('should clone a texture', () => { const baseTexture = new BaseTexture(); const frame = new Rectangle(); @@ -201,27 +208,27 @@ describe('Texture', function () const anchor = new Point(1, 0.5); const texture = new Texture(baseTexture, frame, orig, trim, rotate, anchor); const clone = texture.clone(); - const toJSON = ({ x, y, width, height }) => ({ x, y, width, height }); - - expect(clone.baseTexture).to.equal(baseTexture); - expect(clone.defaultAnchor).to.not.equal(texture.defaultAnchor); - expect(clone.defaultAnchor.x).to.equal(texture.defaultAnchor.x); - expect(clone.defaultAnchor.y).to.equal(texture.defaultAnchor.y); - expect(clone.frame).to.not.equal(texture.frame); - expect(toJSON(clone.frame)).to.deep.equal(toJSON(texture.frame)); - expect(clone.trim).to.not.equal(texture.trim); - expect(toJSON(clone.trim)).to.deep.equal(toJSON(texture.trim)); - expect(clone.orig).to.not.equal(texture.orig); - expect(toJSON(clone.orig)).to.deep.equal(toJSON(texture.orig)); - expect(clone.rotate).to.equal(texture.rotate); - expect(clone.frame === clone.orig).to.equal(texture.frame === texture.orig); - expect(clone.noFrame).to.equal(texture.noFrame); + const toJSON = ({ x, y, width, height }: any) => ({ x, y, width, height }); + + expect(clone.baseTexture).toEqual(baseTexture); + expect(clone.defaultAnchor).not.toBe(texture.defaultAnchor); + expect(clone.defaultAnchor.x).toEqual(texture.defaultAnchor.x); + expect(clone.defaultAnchor.y).toEqual(texture.defaultAnchor.y); + expect(clone.frame).not.toBe(texture.frame); + expect(toJSON(clone.frame)).toEqual(toJSON(texture.frame)); + expect(clone.trim).not.toBe(texture.trim); + expect(toJSON(clone.trim)).toEqual(toJSON(texture.trim)); + expect(clone.orig).not.toBe(texture.orig); + expect(toJSON(clone.orig)).toEqual(toJSON(texture.orig)); + expect(clone.rotate).toEqual(texture.rotate); + expect(clone.frame === clone.orig).toEqual(texture.frame === texture.orig); + expect(clone.noFrame).toEqual(texture.noFrame); clone.destroy(); texture.destroy(true); }); - it('should update frame if its backed by canvas that was resized', function () + it('should update frame if its backed by canvas that was resized', () => { const canvas = document.createElement('canvas'); @@ -230,32 +237,32 @@ describe('Texture', function () const texture = Texture.from(canvas); - expect(texture.noFrame).to.equal(true); - expect(texture.width).to.equal(50); + expect(texture.noFrame).toEqual(true); + expect(texture.width).toEqual(50); canvas.width = 100; texture.update(); - expect(texture.width).to.equal(100); + expect(texture.width).toEqual(100); canvas.height = 70; texture.update(); - expect(texture.height).to.equal(70); + expect(texture.height).toEqual(70); const clone = texture.clone(); - expect(texture.noFrame).to.equal(true); - expect(clone.width).to.equal(100); - expect(clone.height).to.equal(70); + expect(texture.noFrame).toEqual(true); + expect(clone.width).toEqual(100); + expect(clone.height).toEqual(70); canvas.width = 40; clone.update(); - expect(clone.width).to.equal(40); + expect(clone.width).toEqual(40); canvas.height = 60; clone.update(); - expect(clone.height).to.equal(60); + expect(clone.height).toEqual(60); clone.destroy(); texture.destroy(true); }); - it('should update frame on baseTexture update only if user set it in constructor or in setter', function () + it('should update frame on baseTexture update only if user set it in constructor or in setter', () => { let baseTexture = new BaseTexture(); @@ -263,69 +270,109 @@ describe('Texture', function () let texture = new Texture(baseTexture); - expect(texture.noFrame).to.equal(true); - expect(texture.width).to.equal(50); + expect(texture.noFrame).toEqual(true); + expect(texture.width).toEqual(50); baseTexture.setSize(100, 70); - expect(texture.width).to.equal(100); - expect(texture.height).to.equal(70); + expect(texture.width).toEqual(100); + expect(texture.height).toEqual(70); texture.frame = new Rectangle(1, 1, 10, 20); - expect(texture.noFrame).to.equal(false); + expect(texture.noFrame).toEqual(false); baseTexture.setSize(110, 80); - expect(texture.width).to.equal(10); - expect(texture.height).to.equal(20); + expect(texture.width).toEqual(10); + expect(texture.height).toEqual(20); texture.destroy(true); baseTexture = new BaseTexture(); texture = new Texture(baseTexture, new Rectangle(1, 1, 10, 20)); - expect(texture.noFrame).to.equal(false); + expect(texture.noFrame).toEqual(false); baseTexture.setSize(50, 50); - expect(texture.width).to.equal(10); - expect(texture.height).to.equal(20); + expect(texture.width).toEqual(10); + expect(texture.height).toEqual(20); texture.destroy(true); }); - it('should handle loading an invalid URL', function () + it('should throw and error in strict from mode', () => { - expect(() => Texture.fromURL('invalid/image.png')).throws; + const id = 'baz'; + + expect(() => Texture.from(id, {}, true)).toThrowError(`The cacheId "${id}" does not exist in TextureCache.`); + settings.STRICT_TEXTURE_CACHE = true; + expect(() => Texture.from(id)).toThrowError(`The cacheId "${id}" does not exist in TextureCache.`); + settings.STRICT_TEXTURE_CACHE = false; }); - it('should handle loading an cached URL', async function () + describe('Texture.from', () => { - const url = 'noop.png'; + it('should accept & cache a BaseTexture', () => + { + const baseTexture = new BaseTexture(null, { width: 100, height: 100 }); + const texture1 = Texture.from(baseTexture); - TextureCache[url] = Texture.WHITE; + expect(baseTexture.cacheId).not.toBeNull(); + expect(BaseTextureCache[baseTexture.cacheId]).toEqual(baseTexture); + expect(texture1.baseTexture).toEqual(baseTexture); - expect(Texture.WHITE.valid).to.be.true; + expect(Texture.from(baseTexture)).toEqual(texture1); + }); - const texture = await Texture.fromURL(url); + it('should accept an array of strings to create a cubemap', () => + { + const resources = path.join(process.cwd(), 'packages/core/test/resources/'); - expect(texture).equals(Texture.WHITE); - delete TextureCache[url]; - }); + const texture = Texture.from([ + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg')]); - it('should throw and error in strict from mode', function () - { - const id = 'baz'; + expect(texture).not.toBeNull(); + expect(texture).toBeDefined(); - expect(() => Texture.from(id, {}, true)).to.throw(`The cacheId "${id}" does not exist in TextureCache.`); - settings.STRICT_TEXTURE_CACHE = true; - expect(() => Texture.from(id)).to.throw(`The cacheId "${id}" does not exist in TextureCache.`); - settings.STRICT_TEXTURE_CACHE = false; + expect(texture).toBeInstanceOf(Texture); + }); }); - describe('Texture.from', () => + describe('Texture.fromURL', () => { - it('should accept & cache a BaseTexture', () => + it('should handle loading an invalid URL', async () => { - const baseTexture = new BaseTexture(null, { width: 100, height: 100 }); - const texture1 = Texture.from(baseTexture); + const throwingFunction = () => Texture.fromURL('invalid/image.png'); - expect(baseTexture.cacheId).to.not.equal(null); - expect(BaseTextureCache[baseTexture.cacheId]).to.equal(baseTexture); - expect(texture1.baseTexture).to.equal(baseTexture); + await throwingFunction().catch((e) => expect(e).toBeInstanceOf(Event)); + }); - expect(Texture.from(baseTexture)).to.equal(texture1); + it('should handle loading an cached URL', async () => + { + const url = 'noop.png'; + + TextureCache[url] = Texture.WHITE; + + expect(Texture.WHITE.valid).toBe(true); + + const texture = await Texture.fromURL(url); + + expect(texture).toEqual(Texture.WHITE); + delete TextureCache[url]; + }); + + it('should accept an array of strings to create a cubemap', async () => + { + const resources = path.join(__dirname, 'resources'); + + const texture = await Texture.fromURL([ + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg'), + path.join(resources, 'cube-face.jpg')]); + + expect(texture).not.toBeNull(); + expect(texture).toBeDefined(); + expect(texture).toBeInstanceOf(Texture); }); }); }); diff --git a/packages/core/test/TextureSystem.tests.ts b/packages/core/test/TextureSystem.tests.ts index 181cc05f9c4..840437c1278 100644 --- a/packages/core/test/TextureSystem.tests.ts +++ b/packages/core/test/TextureSystem.tests.ts @@ -1,10 +1,11 @@ import { WRAP_MODES, TYPES, FORMATS, SAMPLER_TYPES } from '@pixi/constants'; import { Renderer, Texture, BaseTexture } from '@pixi/core'; -import { expect } from 'chai'; -describe('TextureSystem', function () +describe('TextureSystem', () => { - function createTempTexture(options) + let renderer: Renderer; + + function createTempTexture(options?: Parameters[1]) { const canvas = document.createElement('canvas'); @@ -14,84 +15,85 @@ describe('TextureSystem', function () return BaseTexture.from(canvas, options); } - beforeEach(function () + beforeEach(() => { - this.renderer = new Renderer(); - this.renderer.mask.enableScissor = true; + renderer = new Renderer(); + renderer.mask.enableScissor = true; }); - afterEach(function () + afterEach(() => { - this.renderer.destroy(); - this.renderer = null; + renderer.destroy(); + renderer = null; }); - it('should allow glTexture wrapMode=REPEAT for non-pow2 in webgl2', function () + it('should allow glTexture wrapMode=REPEAT for non-pow2 in webgl2', () => { const baseTex = createTempTexture(); baseTex.wrapMode = WRAP_MODES.REPEAT; - this.renderer.texture.webGLVersion = 2; - this.renderer.texture.bind(baseTex); + renderer.texture['webGLVersion'] = 2; + renderer.texture.bind(baseTex); - const glTex = baseTex._glTextures[this.renderer.CONTEXT_UID]; + const glTex = baseTex._glTextures[renderer.CONTEXT_UID]; - expect(glTex).to.exist; - expect(glTex.wrapMode).to.equal(WRAP_MODES.REPEAT); + expect(glTex).toBeDefined(); + expect(glTex.wrapMode).toEqual(WRAP_MODES.REPEAT); }); - it('should not allow glTexture wrapMode=REPEAT for non-pow2 in webgl1', function () + it('should not allow glTexture wrapMode=REPEAT for non-pow2 in webgl1', () => { const baseTex = createTempTexture(); baseTex.wrapMode = WRAP_MODES.REPEAT; - this.renderer.texture.webGLVersion = 1; - this.renderer.texture.bind(baseTex); + renderer.texture['webGLVersion'] = 1; + renderer.texture.bind(baseTex); - const glTex = baseTex._glTextures[this.renderer.CONTEXT_UID]; + const glTex = baseTex._glTextures[renderer.CONTEXT_UID]; - expect(glTex).to.exist; - expect(glTex.wrapMode).to.equal(WRAP_MODES.CLAMP); + expect(glTex).toBeDefined(); + expect(glTex.wrapMode).toEqual(WRAP_MODES.CLAMP); }); - it('should set internalFormat correctly for RGBA float textures', function () + it('should set internalFormat correctly for RGBA float textures', () => { const baseTex = createTempTexture({ type: TYPES.FLOAT, format: FORMATS.RGBA }); - this.renderer.texture.bind(baseTex); + renderer.texture.bind(baseTex); - const glTex = baseTex._glTextures[this.renderer.CONTEXT_UID]; + const glTex = baseTex._glTextures[renderer.CONTEXT_UID]; - expect(glTex).to.not.be.null; - expect(glTex.internalFormat).to.equal(this.renderer.gl.RGBA32F); + expect(glTex).not.toBeNull(); + expect(glTex.internalFormat).toEqual(renderer.gl.RGBA32F); }); - it('should set internalFormat correctly for red-channel float textures', function () + it('should set internalFormat correctly for red-channel float textures', () => { const baseTex = createTempTexture({ type: TYPES.FLOAT, format: FORMATS.RED }); - this.renderer.texture.bind(baseTex); + renderer.texture.bind(baseTex); - const glTex = baseTex._glTextures[this.renderer.CONTEXT_UID]; + const glTex = baseTex._glTextures[renderer.CONTEXT_UID]; - expect(glTex).to.not.be.null; - expect(glTex.internalFormat).to.equal(this.renderer.gl.R32F); + expect(glTex).not.toBeNull(); + expect(glTex.internalFormat).toEqual(renderer.gl.R32F); }); - it('should set internalFormat correctly for RGB FLOAT textures', function () + it('should set internalFormat correctly for RGB FLOAT textures', () => { const baseTex = createTempTexture({ type: TYPES.FLOAT, format: FORMATS.RGB }); - this.renderer.texture.bind(baseTex); + renderer.texture.bind(baseTex); - const glTex = baseTex._glTextures[this.renderer.CONTEXT_UID]; + const glTex = baseTex._glTextures[renderer.CONTEXT_UID]; - expect(glTex).to.not.be.null; - expect(glTex.internalFormat).to.equal(this.renderer.gl.RGB32F); + expect(glTex).not.toBeNull(); + expect(glTex.internalFormat).toEqual(renderer.gl.RGB32F); }); function createIntegerTexture() { + // @ts-expect-error --- const baseTexture = BaseTexture.fromBuffer(new Uint32Array([0, 0, 0, 0]), 1, 1); const oldUpload = baseTexture.resource.upload.bind(baseTexture); @@ -100,7 +102,7 @@ describe('TextureSystem', function () glTexture.samplerType = SAMPLER_TYPES.INT; if (renderer.context.webGLVersion === 2) { - glTexture.internalFormat = renderer.context.gl.RGBA32I; + glTexture.internalFormat = renderer.context['gl'].RGBA32I; } return oldUpload(renderer, baseTexture, glTexture); @@ -109,9 +111,9 @@ describe('TextureSystem', function () return baseTexture; } - it('should unbind textures with non-float samplerType for batching', function () + it('should unbind textures with non-float samplerType for batching', () => { - const textureSystem = this.renderer.texture; + const textureSystem = renderer.texture; const { boundTextures } = textureSystem; const sampleTex = createIntegerTexture(); const sampleTex2 = createIntegerTexture(); @@ -119,26 +121,26 @@ describe('TextureSystem', function () textureSystem.bind(Texture.WHITE.baseTexture, 0); textureSystem.bind(sampleTex, 1); textureSystem.bind(sampleTex2, 2); - expect(textureSystem.hasIntegerTextures).to.be.true; + expect(textureSystem['hasIntegerTextures']).toBe(true); textureSystem.ensureSamplerType(2); - expect(boundTextures[0]).to.equal(Texture.WHITE.baseTexture); - expect(boundTextures[1]).to.be.null; - expect(boundTextures[2]).to.equal(sampleTex2); + expect(boundTextures[0]).toEqual(Texture.WHITE.baseTexture); + expect(boundTextures[1]).toBeNull(); + expect(boundTextures[2]).toEqual(sampleTex2); }); - it('should bind empty texture if texture is invalid', function () + it('should bind empty texture if texture is invalid', () => { - const textureSystem = this.renderer.texture; + const textureSystem = renderer.texture; - expect(Texture.WHITE.baseTexture.valid).to.be.true; + expect(Texture.WHITE.baseTexture.valid).toBe(true); textureSystem.bind(Texture.WHITE.baseTexture, 0); - expect(textureSystem.boundTextures[0]).to.equal(Texture.WHITE.baseTexture); - expect(Texture.EMPTY.baseTexture.valid).to.be.false; + expect(textureSystem.boundTextures[0]).toEqual(Texture.WHITE.baseTexture); + expect(Texture.EMPTY.baseTexture.valid).toBe(false); textureSystem.bind(Texture.EMPTY.baseTexture, 0); - expect(textureSystem.boundTextures[0]).to.equal(null); + expect(textureSystem.boundTextures[0]).toEqual(null); }); }); diff --git a/packages/core/test/UniformBuffer.tests.ts b/packages/core/test/UniformBuffer.tests.ts index 755a0ef475e..b6ede0111dd 100644 --- a/packages/core/test/UniformBuffer.tests.ts +++ b/packages/core/test/UniformBuffer.tests.ts @@ -1,3 +1,5 @@ +import type { + IRenderingContext } from '@pixi/core'; import { Shader, createUBOElements, @@ -6,9 +8,9 @@ import { Buffer, UniformGroup, generateProgram, - getTestContext, + getTestContext } from '@pixi/core'; -import { expect } from 'chai'; + import { skipHello } from '@pixi/utils'; import { Matrix, Rectangle, Point } from '@pixi/math'; @@ -36,9 +38,9 @@ const stubRenderer = { gl: {} }; -describe('UniformBuffer', function () +describe('UniformBuffer', () => { - it('should generate the correct correctly ordered UBO data', function () + it('should generate the correct correctly ordered UBO data', () => { const uniformData = { uAlpha: { @@ -83,7 +85,7 @@ describe('UniformBuffer', function () value: 0, }]; - expect(usedUniformData).to.deep.equal(expectedResult); + expect(usedUniformData).toEqual(expectedResult); const group2 = UniformGroup.uboFrom({ uAlpha: 1, @@ -92,7 +94,7 @@ describe('UniformBuffer', function () const usedUniformData2 = getUBOData(group2.uniforms, uniformData); - expect(usedUniformData2).to.deep.equal(expectedResult); + expect(usedUniformData2).toEqual(expectedResult); const group3 = UniformGroup.uboFrom({ uAlpha: 1, @@ -102,10 +104,10 @@ describe('UniformBuffer', function () const usedUniformData3 = getUBOData(group3.uniforms, uniformData); - expect(usedUniformData3).to.deep.equal(expectedResult); + expect(usedUniformData3).toEqual(expectedResult); }); - it('should generate correct UBO elements', function () + it('should generate correct UBO elements', () => { const uniformData = [ { name: 'uFloat', index: 1, type: 'float', size: 1, isArray: false, value: 0 }, @@ -145,7 +147,7 @@ describe('UniformBuffer', function () size: 16 }; - expect(uboData).to.deep.equal(expectedObject); + expect(uboData).toEqual(expectedObject); }); it('should generate the correct update function using the parsers', () => @@ -178,7 +180,7 @@ describe('UniformBuffer', function () uRect: new Rectangle(0, 0, 33, 33), }); - const gl = getTestContext(); + const gl = getTestContext() as IRenderingContext; generateProgram(gl, shader.program); @@ -203,13 +205,13 @@ describe('UniformBuffer', function () 0, 0, 33, 33 ]); - expect(size).to.equal(96); - expect(buffer.data).to.deep.equal(expectedBufferValue); + expect(size).toEqual(96); + expect(buffer.data).toEqual(expectedBufferValue); }); it('should write arrays types to buffer correctly', () => { - const gl = getTestContext(); + const gl = getTestContext() as IRenderingContext; [ { @@ -547,7 +549,7 @@ describe('UniformBuffer', function () ]) }, - ].forEach((toTest, i) => + ].forEach((toTest) => { const fragmentSrc = ` #version 300 es @@ -586,7 +588,7 @@ describe('UniformBuffer', function () // console.log('actual ', buffer.data); // } - expect(buffer.data).to.deep.equal(toTest.expectedBuffer); + expect(buffer.data).toEqual(toTest.expectedBuffer); }); }); }); diff --git a/packages/core/test/VideoResource.tests.ts b/packages/core/test/VideoResource.tests.ts index b98e5d39097..0477aac679a 100644 --- a/packages/core/test/VideoResource.tests.ts +++ b/packages/core/test/VideoResource.tests.ts @@ -1,70 +1,73 @@ import { VideoResource } from '@pixi/core'; import path from 'path'; -import { expect } from 'chai'; -describe('VideoResource', function () +describe('VideoResource', () => { - before(function () + let videoUrl: string; + + beforeAll(() => { - this.videoUrl = path.resolve(__dirname, 'resources', 'small.mp4'); + videoUrl = path.resolve(__dirname, 'resources', 'small.mp4'); }); - it('should create new resource', function () + it('should create new resource', () => { - const resource = new VideoResource(this.videoUrl, { autoLoad: false }); + const resource = new VideoResource(videoUrl, { autoLoad: false }); - expect(resource.width).to.equal(0); - expect(resource.height).to.equal(0); - expect(resource.valid).to.be.false; - expect(resource.source).to.be.instanceof(HTMLVideoElement); + expect(resource.width).toEqual(0); + expect(resource.height).toEqual(0); + expect(resource.valid).toBe(false); + expect(resource.source).toBeInstanceOf(HTMLVideoElement); resource.destroy(); }); - it('should load new resource', function () + it('should load new resource', () => { - const resource = new VideoResource(this.videoUrl, { + const resource = new VideoResource(videoUrl, { autoLoad: false, autoPlay: false, }); return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(res.width).to.equal(560); - expect(res.height).to.equal(320); - expect(res.valid).to.be.true; + expect(res).toEqual(resource); + expect(res.width).toEqual(560); + expect(res.height).toEqual(320); + expect(res.valid).toBe(true); resource.destroy(); }); }); - it('should find correct video extension from Url', function () + it('should find correct video extension from Url', () => { const resource = new VideoResource('https://example.org/video.webm', { autoLoad: false, autoPlay: false, }); - expect(resource.source.firstChild.type).to.be.equals('video/webm'); + // @ts-expect-error --- + expect(resource.source.firstChild.type).toEqual('video/webm'); resource.destroy(); }); - it('should get video extension without being thrown by query string', function () + it('should get video extension without being thrown by query string', () => { const resource = new VideoResource('/test.mp4?123...', { autoLoad: false, autoPlay: false, }); - expect(resource.source.firstChild.type).to.be.equals('video/mp4'); + // @ts-expect-error --- + expect(resource.source.firstChild.type).toEqual('video/mp4'); resource.destroy(); }); - it('should respect the updateFPS settings property and getter / setter', function () + it('should respect the updateFPS settings property and getter / setter', () => { - const resource = new VideoResource(this.videoUrl, { + const resource = new VideoResource(videoUrl, { autoLoad: false, autoPlay: false, updateFPS: 30, @@ -72,10 +75,10 @@ describe('VideoResource', function () return resource.load().then((res) => { - expect(res).to.equal(resource); - expect(res.updateFPS).to.equal(30); + expect(res).toEqual(resource); + expect(res.updateFPS).toEqual(30); res.updateFPS = 20; - expect(res.updateFPS).to.equal(20); + expect(res.updateFPS).toEqual(20); resource.destroy(); }); }); diff --git a/packages/core/test/autoDetectResource.tests.ts b/packages/core/test/autoDetectResource.tests.ts index 0534b5e857f..bda8bcd781c 100644 --- a/packages/core/test/autoDetectResource.tests.ts +++ b/packages/core/test/autoDetectResource.tests.ts @@ -1,4 +1,3 @@ -import { expect } from 'chai'; import { autoDetectResource, INSTALLED, CanvasResource, @@ -6,20 +5,20 @@ import { autoDetectResource, VideoResource, SVGResource } from '@pixi/core'; -describe('autoDetectResource', function () +describe('autoDetectResource', () => { - it('should have api', function () + it('should have api', () => { - expect(autoDetectResource).to.be.a('function'); + expect(autoDetectResource).toBeInstanceOf(Function); }); - it('should have installed resources', function () + it('should have installed resources', () => { - expect(INSTALLED).to.be.an('array'); - expect(INSTALLED.length).to.equal(8); + expect(INSTALLED).toBeArray(); + expect(INSTALLED.length).toEqual(8); }); - it('should auto-detect canvas element', function () + it('should auto-detect canvas element', () => { const canvas = document.createElement('canvas'); @@ -28,63 +27,63 @@ describe('autoDetectResource', function () const resource = autoDetectResource(canvas); - expect(resource).is.instanceOf(CanvasResource); - expect(resource.width).to.equal(200); - expect(resource.height).to.equal(100); + expect(resource).toBeInstanceOf(CanvasResource); + expect(resource.width).toEqual(200); + expect(resource.height).toEqual(100); }); - it('should auto-detect video element', function () + it('should auto-detect video element', () => { const video = document.createElement('video'); const resource = autoDetectResource(video); - expect(resource).is.instanceOf(VideoResource); + expect(resource).toBeInstanceOf(VideoResource); }); - it('should auto-detect image element', function () + it('should auto-detect image element', () => { const img = new Image(); const resource = autoDetectResource(img); - expect(resource).is.instanceOf(ImageResource); + expect(resource).toBeInstanceOf(ImageResource); }); - it('should auto-detect image string', function () + it('should auto-detect image string', () => { const img = 'foo.png'; const resource = autoDetectResource(img); - expect(resource).is.instanceOf(ImageResource); + expect(resource).toBeInstanceOf(ImageResource); }); - it('should auto-detect svg string', function () + it('should auto-detect svg string', () => { const svg = 'foo.svg'; const resource = autoDetectResource(svg); - expect(resource).is.instanceOf(SVGResource); + expect(resource).toBeInstanceOf(SVGResource); }); - it('should auto-detect video Url', function () + it('should auto-detect video Url', () => { const video = 'foo.mp4'; const resource = autoDetectResource(video); - expect(resource).is.instanceOf(VideoResource); + expect(resource).toBeInstanceOf(VideoResource); }); - it('should pass null', function () + it('should pass null', () => { const resource = autoDetectResource(null); - expect(resource).to.equal(null); + expect(resource).toEqual(null); }); - it('should throw for unknown types', function () + it('should throw for unknown types', () => { - expect(() => autoDetectResource({})).throws; - expect(() => autoDetectResource(document.createElement('input'))).throws; - expect(() => autoDetectResource(2)).throws; - expect(() => autoDetectResource(true)).throws; + expect(() => autoDetectResource({})).toThrow(); + expect(() => autoDetectResource(document.createElement('input'))).toThrow(); + expect(() => autoDetectResource(2)).toThrow(); + expect(() => autoDetectResource(true)).toThrow(); }); }); diff --git a/packages/core/test/resources/cube-face.jpg b/packages/core/test/resources/cube-face.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfccd62b3f6ff7eff503585f6660b9693d82a8b7 GIT binary patch literal 6247 zcmex=4 zD%dK(z{JSR%*4XX%F4n5R9y>{XJ8Rz6;d>GWD^cdWLGK_F>0K+kVDyN<3Z7&iyu^s zlZu)+xx~aJB&Af<)HO7z=6R={$GRsGhElK z|H8KXvdVvkQ2oC})BiI#WHBfMIpTkdx`CXiS|j_ff%Vrl_J3hreu2?dBw#==A}CjW zK@Q^v4wSg}K?-JuKv$6g!NJI3S&J0P3z!f=c^M^)2PUzCG6`~EjwV>@CGOD#OQRBa zG{I6Yks_DoqX~92!LlM%R-;VyB V1|W|}jFzyYCG0RMVfp{x1OVZff extends DisplayObject { /** * The array of children of this container. - * * @readonly */ - public readonly children: DisplayObject[]; + public readonly children: T[]; /** * If set to true, the container will sort its children by zIndex value @@ -73,7 +68,6 @@ export class Container extends DisplayObject * * Also be aware of that this may not work nicely with the addChildAt() function, * as the zIndex sorting may cause the child to automatically sorted to another position. - * * @see PIXI.settings.SORTABLE_CHILDREN */ public sortableChildren: boolean; @@ -100,7 +94,6 @@ export class Container extends DisplayObject /** * Fired when a DisplayObject is added to this Container. - * * @event PIXI.Container#childAdded * @param {PIXI.DisplayObject} child - The child added to the Container. * @param {PIXI.Container} container - The container that added the child. @@ -109,15 +102,17 @@ export class Container extends DisplayObject /** * Fired when a DisplayObject is removed from this Container. - * - * @event PIXI.DisplayObject#removedFrom + * @event PIXI.DisplayObject#childRemoved * @param {PIXI.DisplayObject} child - The child removed from the Container. - * @param {PIXI.Container} container - The container that removed removed the child. + * @param {PIXI.Container} container - The container that removed the child. * @param {number} index - The former children's index of the removed child */ } - /** Overridable method that can be used by Container subclasses whenever the children array is modified. */ + /** + * Overridable method that can be used by Container subclasses whenever the children array is modified. + * @param _length + */ protected onChildrenChange(_length?: number): void { /* empty */ @@ -127,11 +122,10 @@ export class Container extends DisplayObject * Adds one or more children to the container. * * Multiple items can be added like so: `myContainer.addChild(thingOne, thingTwo, thingThree)` - * * @param {...PIXI.DisplayObject} children - The DisplayObject(s) to add to the container - * @return {PIXI.DisplayObject} - The first child that was added. + * @returns {PIXI.DisplayObject} - The first child that was added. */ - addChild(...children: T): T[0] + addChild(...children: U): U[0] { // if there is only one argument we can bypass looping through the them if (children.length > 1) @@ -175,12 +169,11 @@ export class Container extends DisplayObject /** * Adds a child to the container at a specified index. If the index is out of bounds an error will be thrown - * * @param {PIXI.DisplayObject} child - The child to add * @param {number} index - The index to place the child in - * @return {PIXI.DisplayObject} The child that was added. + * @returns {PIXI.DisplayObject} The child that was added. */ - addChildAt(child: T, index: number): T + addChildAt(child: U, index: number): U { if (index < 0 || index > this.children.length) { @@ -213,11 +206,10 @@ export class Container extends DisplayObject /** * Swaps the position of 2 Display Objects within this container. - * * @param child - First display object to swap * @param child2 - Second display object to swap */ - swapChildren(child: DisplayObject, child2: DisplayObject): void + swapChildren(child: T, child2: T): void { if (child === child2) { @@ -234,11 +226,10 @@ export class Container extends DisplayObject /** * Returns the index position of a child DisplayObject instance - * * @param child - The DisplayObject instance to identify - * @return - The index position of the child display object to identify + * @returns - The index position of the child display object to identify */ - getChildIndex(child: DisplayObject): number + getChildIndex(child: T): number { const index = this.children.indexOf(child); @@ -252,11 +243,10 @@ export class Container extends DisplayObject /** * Changes the position of an existing child in the display object container - * * @param child - The child DisplayObject instance for which you want to change the index number * @param index - The resulting index number for the child display object */ - setChildIndex(child: DisplayObject, index: number): void + setChildIndex(child: T, index: number): void { if (index < 0 || index >= this.children.length) { @@ -265,7 +255,7 @@ export class Container extends DisplayObject const currentIndex = this.getChildIndex(child); - removeItems(this.children, currentIndex, 1); // remove from old position + utils.removeItems(this.children, currentIndex, 1); // remove from old position this.children.splice(index, 0, child); // add at new position this.onChildrenChange(index); @@ -273,11 +263,10 @@ export class Container extends DisplayObject /** * Returns the child at the specified index - * * @param index - The index to get the child at - * @return - The child at the given index, if any. + * @returns - The child at the given index, if any. */ - getChildAt(index: number): DisplayObject + getChildAt(index: number): T { if (index < 0 || index >= this.children.length) { @@ -289,11 +278,10 @@ export class Container extends DisplayObject /** * Removes one or more children from the container. - * * @param {...PIXI.DisplayObject} children - The DisplayObject(s) to remove - * @return {PIXI.DisplayObject} The first child that was removed. + * @returns {PIXI.DisplayObject} The first child that was removed. */ - removeChild(...children: T): T[0] + removeChild(...children: U): U[0] { // if there is only one argument we can bypass looping through the them if (children.length > 1) @@ -314,7 +302,7 @@ export class Container extends DisplayObject child.parent = null; // ensure child transform will be recalculated child.transform._parentID = -1; - removeItems(this.children, index, 1); + utils.removeItems(this.children, index, 1); // ensure bounds will be recalculated this._boundsID++; @@ -330,18 +318,17 @@ export class Container extends DisplayObject /** * Removes a child from the specified index position. - * * @param index - The index to get the child from - * @return The child that was removed. + * @returns The child that was removed. */ - removeChildAt(index: number): DisplayObject + removeChildAt(index: number): T { const child = this.getChildAt(index); // ensure child transform will be recalculated.. child.parent = null; child.transform._parentID = -1; - removeItems(this.children, index, 1); + utils.removeItems(this.children, index, 1); // ensure bounds will be recalculated this._boundsID++; @@ -356,12 +343,11 @@ export class Container extends DisplayObject /** * Removes all children from this container that are within the begin and end indexes. - * * @param beginIndex - The beginning position. * @param endIndex - The ending position. Default value is size of the container. * @returns - List of removed children */ - removeChildren(beginIndex = 0, endIndex = this.children.length): DisplayObject[] + removeChildren(beginIndex = 0, endIndex = this.children.length): T[] { const begin = beginIndex; const end = endIndex; @@ -478,10 +464,18 @@ export class Container extends DisplayObject // TODO: filter+mask, need to mask both somehow if (child._mask) { - const maskObject = ((child._mask as MaskData).maskObject || child._mask) as Container; + const maskObject = ((child._mask as MaskData).isMaskData + ? (child._mask as MaskData).maskObject : child._mask) as Container; - maskObject.calculateBounds(); - this._bounds.addBoundsMask(child._bounds, maskObject._bounds); + if (maskObject) + { + maskObject.calculateBounds(); + this._bounds.addBoundsMask(child._bounds, maskObject._bounds); + } + else + { + this._bounds.addBounds(child._bounds); + } } else if (child.filterArea) { @@ -501,11 +495,10 @@ export class Container extends DisplayObject * * Calling `getLocalBounds` may invalidate the `_bounds` of the whole subtree below. If using it inside a render() * call, it is advised to call `getBounds()` immediately after to recalculate the world bounds of the subtree. - * * @param rect - Optional rectangle to store the result of the bounds calculation. * @param skipChildrenUpdate - Setting to `true` will stop re-calculation of children transforms, * it was default behaviour of pixi 4.0-5.2 and caused many problems to users. - * @return - The rectangular bounding area. + * @returns - The rectangular bounding area. */ public getLocalBounds(rect?: Rectangle, skipChildrenUpdate = false): Rectangle { @@ -530,7 +523,6 @@ export class Container extends DisplayObject /** * Recalculates the content bounds of this object. This should be overriden to * calculate the bounds of this specific object (not including children). - * * @protected */ protected _calculateBounds(): void @@ -540,7 +532,6 @@ export class Container extends DisplayObject /** * Renders this object and its children with culling. - * * @protected * @param {PIXI.Renderer} renderer - The renderer */ @@ -625,7 +616,6 @@ export class Container extends DisplayObject * The [renderAdvanced]{@link PIXI.Container#renderAdvanced} method is internally used when when masking or * filtering is applied on a container. This does, however, break batching and can affect performance when * masking and filtering is applied extensively throughout the scene graph. - * * @param renderer - The renderer */ render(renderer: Renderer): void @@ -637,7 +627,7 @@ export class Container extends DisplayObject } // do a quick check to see if this element has a mask or a filter. - if (this._mask || (this.filters && this.filters.length)) + if (this._mask || this.filters?.length) { this.renderAdvanced(renderer); } @@ -658,7 +648,6 @@ export class Container extends DisplayObject /** * Render the object using the WebGL renderer and advanced features. - * * @param renderer - The renderer */ protected renderAdvanced(renderer: Renderer): void @@ -685,7 +674,7 @@ export class Container extends DisplayObject } } - const flush = (filters && this._enabledFilters && this._enabledFilters.length) + const flush = (filters && this._enabledFilters?.length) || (mask && (!mask.isMaskData || (mask.enabled && (mask.autoDetect || mask.type !== MASK_TYPES.NONE)))); @@ -694,7 +683,7 @@ export class Container extends DisplayObject renderer.batch.flush(); } - if (filters && this._enabledFilters && this._enabledFilters.length) + if (filters && this._enabledFilters?.length) { renderer.filter.push(this, this._enabledFilters); } @@ -728,7 +717,7 @@ export class Container extends DisplayObject renderer.mask.pop(this); } - if (filters && this._enabledFilters && this._enabledFilters.length) + if (filters && this._enabledFilters?.length) { renderer.filter.pop(); } @@ -736,8 +725,7 @@ export class Container extends DisplayObject /** * To be overridden by the subclasses. - * - * @param renderer - The renderer + * @param _renderer - The renderer */ protected _render(_renderer: Renderer): void // eslint-disable-line no-unused-vars { @@ -747,7 +735,6 @@ export class Container extends DisplayObject /** * Removes all internal references and listeners as well as removes children from the display list. * Do not use a Container after calling `destroy`. - * * @param options - Options parameter. A boolean will act as if all options * have been set to that value * @param {boolean} [options.children=false] - if set to true, all the children will have their destroy @@ -757,13 +744,13 @@ export class Container extends DisplayObject * @param {boolean} [options.baseTexture=false] - Only used for child Sprites if options.children is set to true * Should it destroy the base texture of the child sprite */ - destroy(options?: IDestroyOptions|boolean): void + destroy(options?: IDestroyOptions | boolean): void { super.destroy(); this.sortDirty = false; - const destroyChildren = typeof options === 'boolean' ? options : options && options.children; + const destroyChildren = typeof options === 'boolean' ? options : options?.children; const oldChildren = this.removeChildren(0, this.children.length); @@ -824,7 +811,6 @@ export class Container extends DisplayObject /** * Container default updateTransform, does update children of container. * Will crash if there's no parent element. - * * @memberof PIXI.Container# * @method containerUpdateTransform */ diff --git a/packages/display/src/DisplayObject.ts b/packages/display/src/DisplayObject.ts index d9a82690692..bab7be06b46 100644 --- a/packages/display/src/DisplayObject.ts +++ b/packages/display/src/DisplayObject.ts @@ -1,19 +1,17 @@ -import { DEG_TO_RAD, Matrix, Point, RAD_TO_DEG, Rectangle, Transform } from '@pixi/math'; -import { EventEmitter } from '@pixi/utils'; +import { DEG_TO_RAD, RAD_TO_DEG, Rectangle, Transform, utils } from '@pixi/core'; import { Bounds } from './Bounds'; import type { Container } from './Container'; -import type { Filter, MaskData, Renderer } from '@pixi/core'; -import type { IPointData, ObservablePoint } from '@pixi/math'; -import type { Dict } from '@pixi/utils'; +import type { Filter, MaskData, Renderer, IPointData, ObservablePoint, Matrix, Point } from '@pixi/core'; -export interface IDestroyOptions { +export interface IDestroyOptions +{ children?: boolean; texture?: boolean; baseTexture?: boolean; } -export interface DisplayObject extends Omit, EventEmitter {} +export interface DisplayObject extends Omit, utils.EventEmitter {} /** * The base class for all objects that are rendered on the screen. @@ -198,10 +196,9 @@ export interface DisplayObject extends Omit void; /** * Mixes all enumerable properties and methods from a source object to DisplayObject. - * * @param source - The source of properties and methods to mix in. */ - static mixin(source: Dict): void + static mixin(source: utils.Dict): void { // in ES8/ES2017, this would be really easy: // Object.defineProperties(DisplayObject.prototype, Object.getOwnPropertyDescriptors(source)); @@ -395,7 +385,6 @@ export abstract class DisplayObject extends EventEmitter /** * Fired when this DisplayObject is added to a Container. - * * @instance * @event added * @param {PIXI.Container} container - The container added to. @@ -403,15 +392,14 @@ export abstract class DisplayObject extends EventEmitter /** * Fired when this DisplayObject is removed from a Container. - * * @instance * @event removed * @param {PIXI.Container} container - The container removed from. */ /** - * Fired when this DisplayObject is destroyed. - * + * Fired when this DisplayObject is destroyed. This event is emitted once + * destroy is finished. * @instance * @event destroyed */ @@ -429,15 +417,11 @@ export abstract class DisplayObject extends EventEmitter /** * Renders the object using the WebGL renderer. - * * @param renderer - The renderer. */ abstract render(renderer: Renderer): void; - /** - * Recursively updates transform of all objects from the root to this one - * internal function for toLocal() - */ + /** Recursively updates transform of all objects from the root to this one internal function for toLocal() */ protected _recursivePostUpdateTransform(): void { if (this.parent) @@ -451,11 +435,7 @@ export abstract class DisplayObject extends EventEmitter } } - /** - * Updates the object transform for rendering. - * - * TODO - Optimization pass! - */ + /** Updates the object transform for rendering. TODO - Optimization pass! */ updateTransform(): void { this._boundsID++; @@ -476,8 +456,8 @@ export abstract class DisplayObject extends EventEmitter * calling `getBounds` on each object in a subtree will cause the total cost to increase quadratically as * its height increases. * - * * The transforms of all objects in a container's **subtree** and of all **ancestors** are updated. - * * The world bounds of all display objects in a container's **subtree** will also be recalculated. + * The transforms of all objects in a container's **subtree** and of all **ancestors** are updated. + * The world bounds of all display objects in a container's **subtree** will also be recalculated. * * The `_bounds` object stores the last calculation of the bounds. You can use to entirely skip bounds * calculation if needed. @@ -493,12 +473,11 @@ export abstract class DisplayObject extends EventEmitter * `getBounds` should be called with `skipUpdate` equal to `true` in a render() call. This is because the transforms * are guaranteed to be update-to-date. In fact, recalculating inside a render() call may cause corruption in certain * cases. - * * @param skipUpdate - Setting to `true` will stop the transforms of the scene graph from * being updated. This means the calculation returned MAY be out of date BUT will give you a * nice performance boost. * @param rect - Optional rectangle to store the result of the bounds calculation. - * @return - The minimum axis-aligned rectangle in world space that fits around this object. + * @returns - The minimum axis-aligned rectangle in world space that fits around this object. */ getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle { @@ -538,9 +517,8 @@ export abstract class DisplayObject extends EventEmitter /** * Retrieves the local bounds of the displayObject as a rectangle object. - * * @param rect - Optional rectangle to store the result of the bounds calculation. - * @return - The rectangular bounding area. + * @returns - The rectangular bounding area. */ getLocalBounds(rect?: Rectangle): Rectangle { @@ -583,12 +561,11 @@ export abstract class DisplayObject extends EventEmitter /** * Calculates the global position of the display object. - * * @param position - The world origin to calculate from. * @param point - A Point object in which to store the value, optional * (otherwise will create a new Point). * @param skipUpdate - Should we skip the update transform. - * @return - A point object representing the position of this object. + * @returns - A point object representing the position of this object. */ toGlobal

(position: IPointData, point?: P, skipUpdate = false): P { @@ -617,13 +594,12 @@ export abstract class DisplayObject extends EventEmitter /** * Calculates the local position of the display object relative to another point. - * * @param position - The world origin to calculate from. * @param from - The DisplayObject to calculate the global position from. * @param point - A Point object in which to store the value, optional * (otherwise will create a new Point). * @param skipUpdate - Should we skip the update transform - * @return - A point object representing the position of this object + * @returns - A point object representing the position of this object */ toLocal

(position: IPointData, from?: DisplayObject, point?: P, skipUpdate?: boolean): P { @@ -657,9 +633,8 @@ export abstract class DisplayObject extends EventEmitter /** * Set the parent Container of this DisplayObject. - * * @param container - The Container to add this DisplayObject to. - * @return - The Container that this DisplayObject was added to. + * @returns - The Container that this DisplayObject was added to. */ setParent(container: Container): Container { @@ -675,7 +650,6 @@ export abstract class DisplayObject extends EventEmitter /** * Convenience function to set the position, scale, skew and pivot at once. - * * @param x - The X position * @param y - The Y position * @param scaleX - The X scale value @@ -685,7 +659,7 @@ export abstract class DisplayObject extends EventEmitter * @param skewY - The Y skew value * @param pivotX - The X pivot value * @param pivotY - The Y pivot value - * @return - The DisplayObject instance + * @returns - The DisplayObject instance */ setTransform(x = 0, y = 0, scaleX = 1, scaleY = 1, rotation = 0, skewX = 0, skewY = 0, pivotX = 0, pivotY = 0): this { @@ -707,15 +681,15 @@ export abstract class DisplayObject extends EventEmitter * remove the display object from its parent Container as well as remove * all current event listeners and internal references. Do not use a DisplayObject * after calling `destroy()`. + * @param _options */ - destroy(_options?: IDestroyOptions|boolean): void + destroy(_options?: IDestroyOptions | boolean): void { if (this.parent) { this.parent.removeChild(this); } - this.emit('destroyed'); - this.removeAllListeners(); + this._destroyed = true; this.transform = null; this.parent = null; @@ -730,7 +704,8 @@ export abstract class DisplayObject extends EventEmitter this.interactive = false; this.interactiveChildren = false; - this._destroyed = true; + this.emit('destroyed'); + this.removeAllListeners(); } /** @@ -756,7 +731,6 @@ export abstract class DisplayObject extends EventEmitter * elem.updateTransform(); * elem.disableTempParent(cacheParent); * ``` - * * @returns - current parent */ enableTempParent(): Container @@ -770,7 +744,6 @@ export abstract class DisplayObject extends EventEmitter /** * Pair method for `enableTempParent` - * * @param cacheParent - Actual parent of element */ disableTempParent(cacheParent: Container): void @@ -808,7 +781,6 @@ export abstract class DisplayObject extends EventEmitter /** * Current transform of the object based on world (parent) factors. - * * @readonly */ get worldTransform(): Matrix @@ -818,7 +790,6 @@ export abstract class DisplayObject extends EventEmitter /** * Current transform of the object based on local factors: position, scale, other stuff. - * * @readonly */ get localTransform(): Matrix @@ -828,15 +799,14 @@ export abstract class DisplayObject extends EventEmitter /** * The coordinate of the object relative to the local coordinates of the parent. - * - * @since PixiJS 4 + * @since 4.0.0 */ get position(): ObservablePoint { return this.transform.position; } - set position(value: ObservablePoint) + set position(value: IPointData) { this.transform.position.copyFrom(value); } @@ -845,15 +815,14 @@ export abstract class DisplayObject extends EventEmitter * The scale factors of this object along the local coordinate axes. * * The default scale is (1, 1). - * - * @since PixiJS 4 + * @since 4.0.0 */ get scale(): ObservablePoint { return this.transform.scale; } - set scale(value: ObservablePoint) + set scale(value: IPointData) { this.transform.scale.copyFrom(value); } @@ -863,30 +832,28 @@ export abstract class DisplayObject extends EventEmitter * is the projection of `pivot` in the parent's local space. * * By default, the pivot is the origin (0, 0). - * - * @since PixiJS 4 + * @since 4.0.0 */ get pivot(): ObservablePoint { return this.transform.pivot; } - set pivot(value: ObservablePoint) + set pivot(value: IPointData) { this.transform.pivot.copyFrom(value); } /** * The skew factor for the object in radians. - * - * @since PixiJS 4 + * @since 4.0.0 */ get skew(): ObservablePoint { return this.transform.skew; } - set skew(value: ObservablePoint) + set skew(value: IPointData) { this.transform.skew.copyFrom(value); } @@ -925,7 +892,6 @@ export abstract class DisplayObject extends EventEmitter * If a container has the sortableChildren property set to true, children will be automatically * sorted by zIndex value; a higher value will mean it will be moved towards the end of the array, * and thus rendered on top of other display objects within the same container. - * * @see PIXI.Container#sortableChildren */ get zIndex(): number @@ -944,7 +910,6 @@ export abstract class DisplayObject extends EventEmitter /** * Indicates if the object is globally visible. - * * @readonly */ get worldVisible(): boolean @@ -968,10 +933,11 @@ export abstract class DisplayObject extends EventEmitter * Sets a mask for the displayObject. A mask is an object that limits the visibility of an * object to the shape of the mask applied to it. In PixiJS a regular mask must be a * {@link PIXI.Graphics} or a {@link PIXI.Sprite} object. This allows for much faster masking in canvas as it - * utilities shape clipping. To remove a mask, set this property to `null`. + * utilities shape clipping. Furthermore, a mask of an object must be in the subtree of its parent. + * Otherwise, `getLocalBounds` may calculate incorrect bounds, which makes the container's width and height wrong. + * To remove a mask, set this property to `null`. * * For sprite mask both alpha and red channel are used. Black mask is the same as transparent mask. - * * @example * const graphics = new PIXI.Graphics(); * graphics.beginFill(0xFF3300); @@ -980,15 +946,14 @@ export abstract class DisplayObject extends EventEmitter * * const sprite = new PIXI.Sprite(texture); * sprite.mask = graphics; - * * @todo At the moment, PIXI.CanvasRenderer doesn't support PIXI.Sprite as mask. */ - get mask(): Container|MaskData|null + get mask(): Container | MaskData | null { return this._mask; } - set mask(value: Container|MaskData|null) + set mask(value: Container | MaskData | null) { if (this._mask === value) { @@ -997,14 +962,18 @@ export abstract class DisplayObject extends EventEmitter if (this._mask) { - const maskObject = ((this._mask as MaskData).maskObject || this._mask) as Container; + const maskObject = ((this._mask as MaskData).isMaskData + ? (this._mask as MaskData).maskObject : this._mask) as Container; - maskObject._maskRefCount--; - - if (maskObject._maskRefCount === 0) + if (maskObject) { - maskObject.renderable = true; - maskObject.isMask = false; + maskObject._maskRefCount--; + + if (maskObject._maskRefCount === 0) + { + maskObject.renderable = true; + maskObject.isMask = false; + } } } @@ -1012,15 +981,19 @@ export abstract class DisplayObject extends EventEmitter if (this._mask) { - const maskObject = ((this._mask as MaskData).maskObject || this._mask) as Container; + const maskObject = ((this._mask as MaskData).isMaskData + ? (this._mask as MaskData).maskObject : this._mask) as Container; - if (maskObject._maskRefCount === 0) + if (maskObject) { - maskObject.renderable = false; - maskObject.isMask = true; - } + if (maskObject._maskRefCount === 0) + { + maskObject.renderable = false; + maskObject.isMask = true; + } - maskObject._maskRefCount++; + maskObject._maskRefCount++; + } } } } @@ -1039,7 +1012,6 @@ export class TemporaryDisplayObject extends DisplayObject /** * DisplayObject default updateTransform, does not update children of container. * Will crash if there's no parent element. - * * @memberof PIXI.DisplayObject# * @method displayObjectUpdateTransform */ diff --git a/packages/display/src/settings.ts b/packages/display/src/settings.ts index 5de2e343271..fc583d45e09 100644 --- a/packages/display/src/settings.ts +++ b/packages/display/src/settings.ts @@ -1,4 +1,4 @@ -import { settings } from '@pixi/settings'; +import { settings } from '@pixi/core'; /** * Sets the default value for the container property 'sortableChildren'. @@ -11,7 +11,6 @@ import { settings } from '@pixi/settings'; * * Also be aware of that this may not work nicely with the addChildAt() function, * as the zIndex sorting may cause the child to automatically sorted to another position. - * * @static * @constant * @name SORTABLE_CHILDREN diff --git a/packages/display/test/Container.tests.ts b/packages/display/test/Container.tests.ts index 73dc10426de..a4ed1dd3796 100644 --- a/packages/display/test/Container.tests.ts +++ b/packages/display/test/Container.tests.ts @@ -1,469 +1,509 @@ -import { Renderer } from '@pixi/core'; +import { Renderer, Rectangle } from '@pixi/core'; import { Container, DisplayObject } from '@pixi/display'; import { AlphaFilter } from '@pixi/filter-alpha'; import { Graphics } from '@pixi/graphics'; -import { Rectangle } from '@pixi/math'; -import sinon from 'sinon'; -import { expect } from 'chai'; -function testAddChild(fn) +function testAddChild(fn: any) { - return function () + return () => { - fn(function (container, obj) + fn((container: Container, obj: Container) => { container.addChild(obj); }); - fn(function (container, obj) + fn((container: Container, obj: Container) => { + // TODO: is this used? + // @ts-expect-error - legacy test container.addChildAt(obj); }); }; } -function testRemoveChild(fn) +function testRemoveChild(fn: any) { - return function () + return () => { - fn(function (container, obj) + fn((container: Container, obj: Container) => { container.removeChild(obj); }); - fn(function (container, obj) + fn((container: Container, obj: Container) => { container.removeChildAt(container.children.indexOf(obj)); }); - fn(function (container, obj) + fn((container: Container, obj: Container) => { container.removeChildren(container.children.indexOf(obj), container.children.indexOf(obj) + 1); }); }; } -describe('Container', function () +describe('Container', () => { - describe('parent', function () + describe('parent', () => { - it('should be present when adding children to Container', function () + it('should be present when adding children to Container', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); - expect(container.children.length).to.be.equals(0); + expect(container.children.length).toEqual(0); container.addChild(child); - expect(container.children.length).to.be.equals(1); - expect(child.parent).to.be.equals(container); + expect(container.children.length).toEqual(1); + expect(child.parent).toEqual(container); }); }); - describe('events', function () + describe('events', () => { - it('should trigger "added", "removed", "childAdded", and "childRemoved" events on itself and children', function () + it('should trigger "added", "removed", "childAdded", and "childRemoved" events on itself and children', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); let triggeredAdded = false; let triggeredRemoved = false; let triggeredChildAdded = false; let triggeredChildRemoved = false; - child.on('added', (to) => + child.on('added', (to: Container) => { triggeredAdded = true; - expect(container.children.length).to.be.equals(1); - expect(child.parent).to.be.equals(to); + expect(container.children.length).toEqual(1); + expect(child.parent).toEqual(to); }); - child.on('removed', (from) => + child.on('removed', (from: Container) => { triggeredRemoved = true; - expect(container.children.length).to.be.equals(0); - expect(child.parent).to.be.null; - expect(container).to.be.equals(from); + expect(container.children.length).toEqual(0); + expect(child.parent).toBeNull(); + expect(container).toEqual(from); }); container.on('childAdded', (childAdded, containerFrom, index) => { triggeredChildAdded = true; - expect(child).to.be.equals(childAdded); - expect(container).to.be.equals(containerFrom); - expect(index).to.be.equals(0); + expect(child).toEqual(childAdded); + expect(container).toEqual(containerFrom); + expect(index).toEqual(0); }); container.on('childRemoved', (childRemoved, containerFrom, index) => { triggeredChildRemoved = true; - expect(child).to.be.equals(childRemoved); - expect(container).to.be.equals(containerFrom); - expect(index).to.be.equals(0); + expect(child).toEqual(childRemoved); + expect(container).toEqual(containerFrom); + expect(index).toEqual(0); }); container.addChild(child); - expect(triggeredAdded).to.be.true; - expect(triggeredRemoved).to.be.false; - expect(triggeredChildAdded).to.be.true; - expect(triggeredChildRemoved).to.be.false; + expect(triggeredAdded).toBe(true); + expect(triggeredRemoved).toBe(false); + expect(triggeredChildAdded).toBe(true); + expect(triggeredChildRemoved).toBe(false); container.removeChild(child); - expect(triggeredRemoved).to.be.true; - expect(triggeredChildRemoved).to.be.true; + expect(triggeredRemoved).toBe(true); + expect(triggeredChildRemoved).toBe(true); }); }); - describe('addChild', function () + describe('addChild', () => { - it('should remove from current parent', function () + it('should remove from current parent', () => { const parent = new Container(); const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); assertRemovedFromParent(parent, container, child, () => { container.addChild(child); }); }); - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.addChild(child); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(0); }); - it('should flag child transform and container bounds for recalculation', testAddChild(function (mockAddChild) - { - const container = new Container(); - const child = new Container(); + it('should flag child transform and container bounds for recalculation', testAddChild( + (mockAddChild: (container: Container, child: Container) => void) => + { + const container = new Container(); + const child = new Container(); - container.getBounds(); - child.getBounds(); + container.getBounds(); + child.getBounds(); - const boundsID = container._boundsID; - const childParentID = child.transform._parentID; + const boundsID = container['_boundsID']; + const childParentID = child.transform._parentID; - mockAddChild(container, child); + mockAddChild(container, child); - expect(boundsID).to.not.be.equals(container._boundsID); - expect(childParentID).to.not.be.equals(child.transform._parentID); - })); + expect(boundsID).not.toEqual(container['_boundsID']); + expect(childParentID).not.toEqual(child.transform._parentID); + })); }); - describe('removeChildAt', function () + describe('removeChildAt', () => { - it('should remove from current parent', function () + it('should remove from current parent', () => { const parent = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); assertRemovedFromParent(parent, null, child, () => { parent.removeChildAt(0); }); }); - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); container.addChild(child); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.removeChildAt(0); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(0); }); }); - describe('addChildAt', function () + describe('addChildAt', () => { - it('should allow placements at start', function () + it('should allow placements at start', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); container.addChildAt(child, 0); - expect(container.children.length).to.be.equals(2); - expect(container.children[0]).to.be.equals(child); + expect(container.children.length).toEqual(2); + expect(container.children[0]).toEqual(child); }); - it('should allow placements at end', function () + it('should allow placements at end', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); container.addChildAt(child, 1); - expect(container.children.length).to.be.equals(2); - expect(container.children[1]).to.be.equals(child); + expect(container.children.length).toEqual(2); + expect(container.children[1]).toEqual(child); }); - it('should throw on out-of-bounds', function () + it('should throw on out-of-bounds', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); - expect(() => container.addChildAt(child, -1)).to.throw('The index -1 supplied is out of bounds 1'); - expect(() => container.addChildAt(child, 2)).to.throw('The index 2 supplied is out of bounds 1'); + expect(() => container.addChildAt(child, -1)).toThrowError('The index -1 supplied is out of bounds 1'); + expect(() => container.addChildAt(child, 2)).toThrowError('The index 2 supplied is out of bounds 1'); }); - it('should remove from current parent', function () + it('should remove from current parent', () => { const parent = new Container(); const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); assertRemovedFromParent(parent, container, child, () => { container.addChildAt(child, 0); }); }); - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.addChildAt(child, 0); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(0); }); }); - describe('removeChild', function () + describe('removeChild', () => { - it('should ignore non-children', function () + it('should ignore non-children', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); container.addChild(child); + // @ts-expect-error - instantiating DisplayObject container.removeChild(new DisplayObject()); - expect(container.children.length).to.be.equals(1); + expect(container.children.length).toEqual(1); }); - it('should remove all children supplied', function () + it('should remove all children supplied', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); container.addChild(child1, child2); - expect(container.children.length).to.be.equals(2); + expect(container.children.length).toEqual(2); container.removeChild(child1, child2); - expect(container.children.length).to.be.equals(0); + expect(container.children.length).toEqual(0); }); - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); container.addChild(child); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.removeChild(child); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(0); }); - it('should flag transform for recalculation', testRemoveChild(function (mockRemoveChild) - { - const container = new Container(); - const child = new Container(); + it('should flag transform for recalculation', testRemoveChild( + (mockRemoveChild: (c: Container, b: Container) => void) => + { + const container = new Container(); + const child = new Container(); - container.addChild(child); - container.getBounds(); + container.addChild(child); + container.getBounds(); - const childParentID = child.transform._parentID; - const boundsID = container._boundsID; + const childParentID = child.transform._parentID; + const boundsID = container['_boundsID']; - mockRemoveChild(container, child); + mockRemoveChild(container, child); - expect(childParentID).to.not.be.equals(child.transform._parentID); - expect(boundsID).to.not.be.equals(container._boundsID); - })); + expect(childParentID).not.toEqual(child.transform._parentID); + expect(boundsID).not.toEqual(container['_boundsID']); + })); }); - describe('getChildIndex', function () + describe('getChildIndex', () => { - it('should return the correct index', function () + it('should return the correct index', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject(), child, new DisplayObject()); - expect(container.getChildIndex(child)).to.be.equals(1); + expect(container.getChildIndex(child)).toEqual(1); }); - it('should throw when child does not exist', function () + it('should throw when child does not exist', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); expect(() => container.getChildIndex(child)) - .to.throw('The supplied DisplayObject must be a child of the caller'); + .toThrowError('The supplied DisplayObject must be a child of the caller'); }); }); - describe('getChildAt', function () + describe('getChildAt', () => { - it('should throw when out-of-bounds', function () + it('should throw when out-of-bounds', () => { const container = new Container(); - expect(() => container.getChildAt(-1)).to.throw('getChildAt: Index (-1) does not exist.'); - expect(() => container.getChildAt(1)).to.throw('getChildAt: Index (1) does not exist.'); + expect(() => container.getChildAt(-1)).toThrowError('getChildAt: Index (-1) does not exist.'); + expect(() => container.getChildAt(1)).toThrowError('getChildAt: Index (1) does not exist.'); }); }); - describe('setChildIndex', function () + describe('setChildIndex', () => { - it('should throw on out-of-bounds', function () + it('should throw on out-of-bounds', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); container.addChild(child); - expect(() => container.setChildIndex(child, -1)).to.throw('The index -1 supplied is out of bounds 1'); - expect(() => container.setChildIndex(child, 1)).to.throw('The index 1 supplied is out of bounds 1'); + expect(() => container.setChildIndex(child, -1)).toThrowError('The index -1 supplied is out of bounds 1'); + expect(() => container.setChildIndex(child, 1)).toThrowError('The index 1 supplied is out of bounds 1'); }); - it('should throw when child does not belong', function () + it('should throw when child does not belong', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); expect(() => container.setChildIndex(child, 0)) - .to.throw('The supplied DisplayObject must be a child of the caller'); + .toThrowError('The supplied DisplayObject must be a child of the caller'); }); - it('should set index', function () + it('should set index', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(child, new DisplayObject(), new DisplayObject()); - expect(container.children.indexOf(child)).to.be.equals(0); + expect(container.children.indexOf(child)).toEqual(0); container.setChildIndex(child, 1); - expect(container.children.indexOf(child)).to.be.equals(1); + expect(container.children.indexOf(child)).toEqual(1); container.setChildIndex(child, 2); - expect(container.children.indexOf(child)).to.be.equals(2); + expect(container.children.indexOf(child)).toEqual(2); container.setChildIndex(child, 0); - expect(container.children.indexOf(child)).to.be.equals(0); + expect(container.children.indexOf(child)).toEqual(0); }); - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(child, new DisplayObject()); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.setChildIndex(child, 1); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(1); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(1); }); }); - describe('swapChildren', function () + describe('swapChildren', () => { - it('should call onChildrenChange', function () + it('should call onChildrenChange', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); container.addChild(child1, child2); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.swapChildren(child1, child2); - expect(spy).to.have.been.called; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalled(); + expect(spy).toBeCalledWith(0); // second call required to complete returned index coverage container.swapChildren(child1, child2); - expect(spy).to.have.been.calledTwice; - expect(spy).to.have.been.calledWith(0); + expect(spy).toBeCalledTimes(2); + expect(spy).toBeCalledWith(0); }); - it('should not call onChildrenChange if supplied children are equal', function () + it('should not call onChildrenChange if supplied children are equal', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject container.addChild(child, new DisplayObject()); - const spy = sinon.spy(container, 'onChildrenChange'); + const spy = jest.spyOn(container, 'onChildrenChange' as any); container.swapChildren(child, child); - expect(spy).to.not.have.been.called; + expect(spy).not.toBeCalled(); }); - it('should throw if children do not belong', function () + it('should throw if children do not belong', () => { const container = new Container(); const child = new Container(); + // @ts-expect-error - instantiating DisplayObject container.addChild(child, new DisplayObject()); + // @ts-expect-error - instantiating DisplayObject expect(() => container.swapChildren(child, new DisplayObject())) - .to.throw('The supplied DisplayObject must be a child of the caller'); + .toThrowError('The supplied DisplayObject must be a child of the caller'); + // @ts-expect-error - instantiating DisplayObject expect(() => container.swapChildren(new DisplayObject(), child)) - .to.throw('The supplied DisplayObject must be a child of the caller'); + .toThrowError('The supplied DisplayObject must be a child of the caller'); }); - it('should result in swapped child positions', function () + it('should result in swapped child positions', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); container.addChild(child1, child2); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); container.swapChildren(child1, child2); - expect(container.children.indexOf(child2)).to.be.equals(0); - expect(container.children.indexOf(child1)).to.be.equals(1); + expect(container.children.indexOf(child2)).toEqual(0); + expect(container.children.indexOf(child1)).toEqual(1); }); }); - describe('updateTransform', function () + describe('updateTransform', () => { - it('should call sortChildren if sortDirty and sortableChildren are true', function () + it('should call sortChildren if sortDirty and sortableChildren are true', () => { const parent = new Container(); const container = new Container(); const child = new Container(); - const canvasSpy = sinon.spy(container, 'sortChildren'); + const canvasSpy = jest.spyOn(container, 'sortChildren'); parent.addChild(container); container.addChild(child); @@ -473,15 +513,15 @@ describe('Container', function () container.updateTransform(); - expect(canvasSpy).to.have.been.called; + expect(canvasSpy).toBeCalled(); }); - it('should not call sortChildren if sortDirty is false', function () + it('should not call sortChildren if sortDirty is false', () => { const parent = new Container(); const container = new Container(); const child = new Container(); - const canvasSpy = sinon.spy(container, 'sortChildren'); + const canvasSpy = jest.spyOn(container, 'sortChildren'); parent.addChild(container); container.addChild(child); @@ -491,15 +531,15 @@ describe('Container', function () container.updateTransform(); - expect(canvasSpy).to.not.have.been.called; + expect(canvasSpy).not.toBeCalled(); }); - it('should not call sortChildren if sortableChildren is false', function () + it('should not call sortChildren if sortableChildren is false', () => { const parent = new Container(); const container = new Container(); const child = new Container(); - const canvasSpy = sinon.spy(container, 'sortChildren'); + const canvasSpy = jest.spyOn(container, 'sortChildren'); parent.addChild(container); container.addChild(child); @@ -509,150 +549,156 @@ describe('Container', function () container.updateTransform(); - expect(canvasSpy).to.not.have.been.called; + expect(canvasSpy).not.toBeCalled(); }); }); - describe('render', function () + describe('render', () => { - it('should not render when object not visible', function () + it('should not render when object not visible', () => { const container = new Container(); - const webGLSpy = sinon.spy(container._render); + const webGLSpy = jest.spyOn(container, '_render' as any); container.visible = false; - container.render(); - expect(webGLSpy).to.not.have.been.called; + container.render(undefined); + expect(webGLSpy).not.toBeCalled(); }); - it('should not render when alpha is zero', function () + it('should not render when alpha is zero', () => { const container = new Container(); - const webGLSpy = sinon.spy(container._render); + const webGLSpy = jest.spyOn(container, '_render' as any); container.worldAlpha = 0; - container.render(); - expect(webGLSpy).to.not.have.been.called; + container.render(undefined); + expect(webGLSpy).not.toBeCalled(); }); - it('should not render when object not renderable', function () + it('should not render when object not renderable', () => { const container = new Container(); - const webGLSpy = sinon.spy(container._render); + const webGLSpy = jest.spyOn(container, '_render' as any); container.renderable = false; - container.render(); - expect(webGLSpy).to.not.have.been.called; + container.render(undefined); + expect(webGLSpy).not.toBeCalled(); }); - it('should render children', function () + it('should render children', () => { const container = new Container(); const child = new Container(); - const webGLSpy = sinon.spy(child, '_render'); + const webGLSpy = jest.spyOn(child, '_render' as any); container.addChild(child); - container.render(); - expect(webGLSpy).to.have.been.called; + container.render(undefined); + expect(webGLSpy).toBeCalled(); }); }); - describe('removeChildren', function () + describe('removeChildren', () => { - it('should remove all children when no arguments supplied', function () + it('should remove all children when no arguments supplied', () => { const container = new Container(); let removed = []; + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject(), new DisplayObject(), new DisplayObject()); - expect(container.children.length).to.be.equals(3); + expect(container.children.length).toEqual(3); removed = container.removeChildren(); - expect(container.children.length).to.be.equals(0); - expect(removed.length).to.be.equals(3); + expect(container.children.length).toEqual(0); + expect(removed.length).toEqual(3); }); - it('should return empty array if no children', function () + it('should return empty array if no children', () => { const container = new Container(); const removed = container.removeChildren(); - expect(removed.length).to.be.equals(0); + expect(removed.length).toEqual(0); }); - it('should handle a range greater than length', function () + it('should handle a range greater than length', () => { const container = new Container(); let removed = []; + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); removed = container.removeChildren(0, 2); - expect(removed.length).to.be.equals(1); + expect(removed.length).toEqual(1); }); - it('should throw outside acceptable range', function () + it('should throw outside acceptable range', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject container.addChild(new DisplayObject()); expect(() => container.removeChildren(2)) - .to.throw('removeChildren: numeric values are outside the acceptable range.'); + .toThrowError('removeChildren: numeric values are outside the acceptable range.'); expect(() => container.removeChildren(-1)) - .to.throw('removeChildren: numeric values are outside the acceptable range.'); + .toThrowError('removeChildren: numeric values are outside the acceptable range.'); expect(() => container.removeChildren(-1, 1)) - .to.throw('removeChildren: numeric values are outside the acceptable range.'); + .toThrowError('removeChildren: numeric values are outside the acceptable range.'); }); }); - describe('destroy', function () + describe('destroy', () => { - it('should not destroy children by default', function () + it('should not destroy children by default', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); container.addChild(child); container.destroy(); - expect(container.children.length).to.be.equals(0); - expect(child.transform).to.not.be.null; + expect(container.children.length).toEqual(0); + expect(child.transform).not.toBeNull(); }); - it('should allow children destroy', function () + it('should allow children destroy', () => { let container = new Container(); + // @ts-expect-error - instantiating DisplayObject let child = new DisplayObject(); container.addChild(child); container.destroy({ children: true }); - expect(container.children.length).to.be.equals(0); - expect(container.transform).to.be.null; - expect(child.transform).to.be.null; + expect(container.children.length).toEqual(0); + expect(container.transform).toBeNull(); + expect(child.transform).toBeNull(); container = new Container(); + // @ts-expect-error - instantiating DisplayObject child = new DisplayObject(); container.addChild(child); container.destroy(true); - expect(container.children.length).to.be.equals(0); - expect(container.transform).to.be.null; - expect(child.transform).to.be.null; + expect(container.children.length).toEqual(0); + expect(container.transform).toBeNull(); + expect(child.transform).toBeNull(); }); }); - describe('getLocalBounds', function () + describe('getLocalBounds', () => { - it('should recalculate children transform by default', function () + it('should recalculate children transform by default', () => { const root = new Container(); const container = new Container(); @@ -667,18 +713,19 @@ describe('Container', function () container.updateTransform(); container.getLocalBounds(); - expect(child.transform.worldTransform.tx).to.equal(30); - expect(child.transform.worldTransform.ty).to.equal(40); + expect(child.transform.worldTransform.tx).toEqual(30); + expect(child.transform.worldTransform.ty).toEqual(40); }); - it('should recalculate bounds if children position was changed', function () + it('should recalculate bounds if children position was changed', () => { const root = new Container(); const container = new Container(); const child = new Container(); let bounds = null; - child._calculateBounds = function () + // eslint-disable-next-line func-names + child['_calculateBounds'] = function () { this._bounds.addFrame(this.transform, 0, 0, 1, 1); }; @@ -690,60 +737,62 @@ describe('Container', function () child.position.set(20, 30); bounds = container.getLocalBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(30); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(30); child.position.set(5, 5); bounds = container.getLocalBounds(); - expect(bounds.x).to.equal(5); - expect(bounds.y).to.equal(5); + expect(bounds.x).toEqual(5); + expect(bounds.y).toEqual(5); }); }); - describe('width', function () + describe('width', () => { - it('should reset scale', function () + it('should reset scale', () => { const container = new Container(); container.scale.x = 2; container.width = 5; - expect(container.width).to.be.equals(0); - expect(container.scale.x).to.be.equals(1); + expect(container.width).toEqual(0); + expect(container.scale.x).toEqual(1); }); }); - describe('height', function () + describe('height', () => { - it('should reset scale', function () + it('should reset scale', () => { const container = new Container(); container.scale.y = 2; container.height = 5; - expect(container.height).to.be.equals(0); - expect(container.scale.y).to.be.equals(1); + expect(container.height).toEqual(0); + expect(container.scale.y).toEqual(1); }); }); - describe('sortDirty', function () + describe('sortDirty', () => { - it('should set sortDirty flag to true when adding a new child', function () + it('should set sortDirty flag to true when adding a new child', () => { const parent = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); - expect(parent.sortDirty).to.be.false; + expect(parent.sortDirty).toBe(false); parent.addChild(child); - expect(parent.sortDirty).to.be.true; + expect(parent.sortDirty).toBe(true); }); - it('should set sortDirty flag to true when changing a child zIndex', function () + it('should set sortDirty flag to true when changing a child zIndex', () => { const parent = new Container(); + // @ts-expect-error - instantiating DisplayObject const child = new DisplayObject(); parent.addChild(child); @@ -752,13 +801,13 @@ describe('Container', function () child.zIndex = 10; - expect(parent.sortDirty).to.be.true; + expect(parent.sortDirty).toBe(true); }); }); - describe('sortChildren', function () + describe('sortChildren', () => { - it('should reset sortDirty flag', function () + it('should reset sortDirty flag', () => { const container = new Container(); @@ -766,44 +815,52 @@ describe('Container', function () container.sortChildren(); - expect(container.sortDirty).to.be.false; + expect(container.sortDirty).toBe(false); }); - it('should call sort when at least one child has a zIndex', function () + it('should call sort when at least one child has a zIndex', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); - const spy = sinon.spy(container.children, 'sort'); + const spy = jest.spyOn(container.children, 'sort' as any); child1.zIndex = 5; container.addChild(child1, child2); container.sortChildren(); - expect(spy).to.have.been.called; + expect(spy).toBeCalled(); }); - it('should not call sort when children have no zIndex', function () + it('should not call sort when children have no zIndex', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); - const spy = sinon.spy(container.children, 'sort'); + const spy = jest.spyOn(container.children, 'sort' as any); container.addChild(child1, child2); container.sortChildren(); - expect(spy).to.not.have.been.called; + expect(spy).not.toBeCalled(); }); - it('should sort children by zIndex value', function () + it('should sort children by zIndex value', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child3 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child4 = new DisplayObject(); child1.zIndex = 20; @@ -812,25 +869,29 @@ describe('Container', function () container.addChild(child1, child2, child3, child4); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(3); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(3); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(3); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(3); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(0); }); - it('should sort children by current array order if zIndex values match', function () + it('should sort children by current array order if zIndex values match', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child3 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child4 = new DisplayObject(); child1.zIndex = 20; @@ -840,30 +901,34 @@ describe('Container', function () container.addChild(child1, child2, child3, child4); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(3); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(3); container.sortChildren(); - expect(child1._lastSortedIndex).to.be.equals(0); - expect(child2._lastSortedIndex).to.be.equals(1); - expect(child3._lastSortedIndex).to.be.equals(2); - expect(child4._lastSortedIndex).to.be.equals(3); + expect(child1._lastSortedIndex).toEqual(0); + expect(child2._lastSortedIndex).toEqual(1); + expect(child3._lastSortedIndex).toEqual(2); + expect(child4._lastSortedIndex).toEqual(3); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(3); - expect(container.children.indexOf(child3)).to.be.equals(0); - expect(container.children.indexOf(child4)).to.be.equals(1); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(3); + expect(container.children.indexOf(child3)).toEqual(0); + expect(container.children.indexOf(child4)).toEqual(1); }); - it('should sort children in the same way despite being called multiple times', function () + it('should sort children in the same way despite being called multiple times', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child3 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child4 = new DisplayObject(); child1.zIndex = 10; @@ -873,24 +938,24 @@ describe('Container', function () container.addChild(child1, child2, child3, child4); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(3); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(3); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(3); - expect(container.children.indexOf(child3)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(3); + expect(container.children.indexOf(child3)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(0); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(3); - expect(container.children.indexOf(child3)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(3); + expect(container.children.indexOf(child3)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(0); child1.zIndex = 1; child2.zIndex = 1; @@ -899,18 +964,22 @@ describe('Container', function () container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(3); - expect(container.children.indexOf(child3)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(3); + expect(container.children.indexOf(child3)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(0); }); - it('should sort new children added correctly', function () + it('should sort new children added correctly', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child3 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child4 = new DisplayObject(); child1.zIndex = 20; @@ -919,37 +988,41 @@ describe('Container', function () container.addChild(child1, child2, child3); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(0); - expect(container.children.indexOf(child3)).to.be.equals(1); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(0); + expect(container.children.indexOf(child3)).toEqual(1); container.addChild(child4); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(0); - expect(container.children.indexOf(child3)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(3); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(0); + expect(container.children.indexOf(child3)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(3); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(3); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(3); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(0); }); - it('should sort children after a removal correctly', function () + it('should sort children after a removal correctly', () => { const container = new Container(); + // @ts-expect-error - instantiating DisplayObject const child1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child2 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child3 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayObject const child4 = new DisplayObject(); child1.zIndex = 20; @@ -958,68 +1031,70 @@ describe('Container', function () container.addChild(child1, child2, child3, child4); - expect(container.children.indexOf(child1)).to.be.equals(0); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(3); + expect(container.children.indexOf(child1)).toEqual(0); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(3); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(3); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child3)).to.be.equals(2); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(3); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child3)).toEqual(2); + expect(container.children.indexOf(child4)).toEqual(0); container.removeChild(child3); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(0); container.sortChildren(); - expect(container.children.indexOf(child1)).to.be.equals(2); - expect(container.children.indexOf(child2)).to.be.equals(1); - expect(container.children.indexOf(child4)).to.be.equals(0); + expect(container.children.indexOf(child1)).toEqual(2); + expect(container.children.indexOf(child2)).toEqual(1); + expect(container.children.indexOf(child4)).toEqual(0); }); }); - function assertRemovedFromParent(parent, container, child, functionToAssert) + function assertRemovedFromParent(parent: Container, container: Container, child: Container, functionToAssert: () => void) { parent.addChild(child); - expect(parent.children.length).to.be.equals(1); - expect(child.parent).to.be.equals(parent); + expect(parent.children.length).toEqual(1); + expect(child.parent).toEqual(parent); functionToAssert(); - expect(parent.children.length).to.be.equals(0); - expect(child.parent).to.be.equals(container); + expect(parent.children.length).toEqual(0); + expect(child.parent).toEqual(container); } - describe('culling', function () + describe('culling', () => { - before(function () + let renderer: Renderer; + let filterPush: jest.SpyInstance; + + beforeAll(() => { - this.renderer = new Renderer({ width: 100, height: 100 }); - this.filterPush = sinon.spy(this.renderer.filter, 'push'); + renderer = new Renderer({ width: 100, height: 100 }); + filterPush = jest.spyOn(renderer.filter, 'push'); }); - after(function () + afterAll(() => { - this.renderer.destroy(); - this.renderer = null; - this.filterPush = null; + renderer.destroy(); + renderer = null; + filterPush = null; }); - afterEach(function () + afterEach(() => { - this.filterPush.resetHistory(); + filterPush.mockClear(); }); - it('noncullable container should always be rendered even if bounds do not intersect the frame', function () + it('noncullable container should always be rendered even if bounds do not intersect the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); @@ -1027,18 +1102,17 @@ describe('Container', function () graphics.x = -1000; graphics.y = -1000; - const _renderContainer = sinon.spy(container, '_render'); - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderContainer).to.have.been.called; - expect(_renderGraphics).to.have.been.called; + expect(_renderContainer).toBeCalled(); + expect(_renderGraphics).toBeCalled(); }); - it('cullable container should not be rendered if bounds do not intersect the frame', function () + it('cullable container should not be rendered if bounds do not intersect the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); @@ -1046,18 +1120,17 @@ describe('Container', function () graphics.x = 0; graphics.y = -10; - const _renderContainer = sinon.spy(container, '_render'); - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderContainer).to.not.have.been.called; - expect(_renderGraphics).to.not.have.been.called; + expect(_renderContainer).not.toBeCalled(); + expect(_renderGraphics).not.toBeCalled(); }); - it('cullable container should be rendered if bounds intersects the frame', function () + it('cullable container should be rendered if bounds intersects the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); @@ -1065,20 +1138,19 @@ describe('Container', function () graphics.x = 0; graphics.y = -9; - const _renderContainer = sinon.spy(container, '_render'); - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderContainer).to.have.been.called; - expect(_renderGraphics).to.have.been.called; + expect(_renderContainer).toBeCalled(); + expect(_renderGraphics).toBeCalled(); }); it('cullable container that contains a child with a padded filter (autoFit=true) ' + 'such that the child in out of frame but the filter padding intersects the frame ' - + 'should render the filter padding but not the container or child', function () + + 'should render the filter padding but not the container or child', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); const filter = new AlphaFilter(); @@ -1091,21 +1163,20 @@ describe('Container', function () graphics.x = 0; graphics.y = -15; - const _renderContainer = sinon.spy(container, '_render'); - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderContainer).to.not.have.been.called; - expect(_renderGraphics).to.not.have.been.called; - expect(this.filterPush).to.have.been.called; + expect(_renderContainer).not.toBeCalled(); + expect(_renderGraphics).not.toBeCalled(); + expect(filterPush).toBeCalled(); }); it('cullable container that contains a child with a padded filter (autoFit=false) ' + 'such that the child in out of frame but the filter padding intersects the frame ' - + 'should render the filtered child but not the container', function () + + 'should render the filtered child but not the container', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); const filter = new AlphaFilter(); @@ -1118,20 +1189,19 @@ describe('Container', function () graphics.x = 0; graphics.y = -15; - const _renderContainer = sinon.spy(container, '_render'); - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderContainer).to.not.have.been.called; - expect(_renderGraphics).to.have.been.called; - expect(this.filterPush).to.have.been.called; + expect(_renderContainer).not.toBeCalled(); + expect(_renderGraphics).toBeCalled(); + expect(filterPush).toBeCalled(); }); it('cullable container with a filter (autoFit=true) should not render the container or children ' - + 'if the bounds as well as the filter padding do no intersect the frame', function () + + 'if the bounds as well as the filter padding do no intersect the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); const filter = new AlphaFilter(); @@ -1144,19 +1214,18 @@ describe('Container', function () graphics.x = 0; graphics.y = -15; - const _renderContainer = sinon.spy(container, '_render'); - const renderGraphics = sinon.spy(graphics, 'render'); + const _renderContainer = jest.spyOn(container, '_render' as any); + const renderGraphics = jest.spyOn(graphics, 'render'); renderer.render(container); - expect(_renderContainer).to.not.have.been.called; - expect(renderGraphics).to.not.have.been.called; - expect(this.filterPush).to.have.been.called; + expect(_renderContainer).not.toBeCalled(); + expect(renderGraphics).not.toBeCalled(); + expect(filterPush).toBeCalled(); }); - it('cullable container with cullArea should be rendered if the bounds intersect the frame', function () + it('cullable container with cullArea should be rendered if the bounds intersect the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); @@ -1165,16 +1234,15 @@ describe('Container', function () container.x = container.y = 107.07; container.rotation = Math.PI / 4; - const _renderGraphics = sinon.spy(graphics, '_render'); + const _renderGraphics = jest.spyOn(graphics, '_render' as any); renderer.render(container); - expect(_renderGraphics).to.have.been.called; + expect(_renderGraphics).toBeCalled(); }); - it('cullable container with cullArea should not be rendered if the bounds do not intersect the frame', function () + it('cullable container with cullArea should not be rendered if the bounds do not intersect the frame', () => { - const renderer = this.renderer; const container = new Container(); const graphics = container.addChild(new Graphics().beginFill().drawRect(0, 0, 10, 10).endFill()); @@ -1183,11 +1251,11 @@ describe('Container', function () container.x = container.y = 107.08; container.rotation = Math.PI / 4; - const renderGraphics = sinon.spy(graphics, 'render'); + const renderGraphics = jest.spyOn(graphics, 'render'); renderer.render(container); - expect(renderGraphics).to.not.have.been.called; + expect(renderGraphics).not.toBeCalled(); }); }); }); diff --git a/packages/display/test/DisplayObject.tests.ts b/packages/display/test/DisplayObject.tests.ts index a4df3c6c1ac..0064bacea86 100755 --- a/packages/display/test/DisplayObject.tests.ts +++ b/packages/display/test/DisplayObject.tests.ts @@ -1,120 +1,126 @@ import { DisplayObject, Container } from '@pixi/display'; -import { RAD_TO_DEG, DEG_TO_RAD } from '@pixi/math'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { RAD_TO_DEG, DEG_TO_RAD } from '@pixi/core'; -describe('DisplayObject', function () +describe('DisplayObject', () => { - describe('constructor', function () + describe('constructor', () => { - it('should initialise properties', function () + it('should initialise properties', () => { + // @ts-expect-error - instantiating DisplayOBject const object = new DisplayObject(); - expect(object.alpha).to.equal(1); - expect(object.worldAlpha).to.equal(1); - expect(object.renderable).to.be.true; - expect(object.visible).to.be.true; + expect(object.alpha).toEqual(1); + expect(object.worldAlpha).toEqual(1); + expect(object.renderable).toBe(true); + expect(object.visible).toBe(true); }); }); - describe('setParent', function () + describe('setParent', () => { - it('should add itself to a Container', function () + it('should add itself to a Container', () => { + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); const container = new Container(); - expect(container.children.length).to.equal(0); + expect(container.children.length).toEqual(0); child.setParent(container); - expect(container.children.length).to.equal(1); - expect(child.parent).to.equal(container); + expect(container.children.length).toEqual(1); + expect(child.parent).toEqual(container); }); - it('should throw if not Container', function () + it('should throw if not Container', () => { + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); const notAContainer = {}; - expect(() => child.setParent()).to.throw('setParent: Argument must be a Container'); - expect(() => child.setParent(notAContainer)).to.throw('setParent: Argument must be a Container'); + expect(() => child.setParent()).toThrowError('setParent: Argument must be a Container'); + expect(() => child.setParent(notAContainer)).toThrowError('setParent: Argument must be a Container'); }); }); - describe('setTransform', function () + describe('setTransform', () => { - it('should set correct properties', function () + it('should set correct properties', () => { + // @ts-expect-error - instantiating DisplayOBject const object = new DisplayObject(); object.setTransform(1, 2, 3, 4, 5, 6, 7, 8, 9); - expect(object.position.x).to.be.equal(1); - expect(object.position.y).to.be.equal(2); - expect(object.scale.x).to.be.equal(3); - expect(object.scale.y).to.be.equal(4); - expect(object.rotation).to.be.equal(5); - expect(object.skew.x).to.be.equal(6); - expect(object.skew.y).to.be.equal(7); - expect(object.pivot.x).to.be.equal(8); - expect(object.pivot.y).to.be.equal(9); + expect(object.position.x).toEqual(1); + expect(object.position.y).toEqual(2); + expect(object.scale.x).toEqual(3); + expect(object.scale.y).toEqual(4); + expect(object.rotation).toEqual(5); + expect(object.skew.x).toEqual(6); + expect(object.skew.y).toEqual(7); + expect(object.pivot.x).toEqual(8); + expect(object.pivot.y).toEqual(9); }); - it('should convert zero scale to one', function () + it('should convert zero scale to one', () => { + // @ts-expect-error - instantiating DisplayOBject const object = new DisplayObject(); object.setTransform(1, 1, 0, 0, 1, 1, 1, 1, 1); - expect(object.scale.x).to.be.equal(1); - expect(object.scale.y).to.be.equal(1); + expect(object.scale.x).toEqual(1); + expect(object.scale.y).toEqual(1); }); }); - describe('worldVisible', function () + describe('worldVisible', () => { - it('should traverse parents', function () + it('should traverse parents', () => { const grandParent = new Container(); const parent = new Container(); + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); grandParent.addChild(parent); parent.addChild(child); - expect(child.worldVisible).to.be.true; + expect(child.worldVisible).toBe(true); grandParent.visible = false; - expect(child.worldVisible).to.be.false; + expect(child.worldVisible).toBe(false); }); }); - describe('rotation', function () + describe('rotation', () => { - it('rotation and angle are different units of the same transformation', function () + it('rotation and angle are different units of the same transformation', () => { + // @ts-expect-error - instantiating DisplayOBject const object = new DisplayObject(); - expect(object.rotation).to.be.equal(0); - expect(object.angle).to.be.equal(0); + expect(object.rotation).toEqual(0); + expect(object.angle).toEqual(0); object.rotation = 2; - expect(object.rotation).to.be.equal(2); - expect(object.angle).to.be.equal(2 * RAD_TO_DEG); + expect(object.rotation).toEqual(2); + expect(object.angle).toEqual(2 * RAD_TO_DEG); object.angle = 180; - expect(object.rotation).to.be.equal(180 * DEG_TO_RAD); - expect(object.angle).to.be.equal(180); + expect(object.rotation).toEqual(180 * DEG_TO_RAD); + expect(object.angle).toEqual(180); }); }); - describe('enableTempParent', function () + describe('enableTempParent', () => { - it('should allow to recalc children transform', function () + it('should allow to recalc children transform', () => { + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); const container = new Container(); @@ -126,108 +132,111 @@ describe('DisplayObject', function () container.updateTransform(); container.disableTempParent(null); - expect(child.worldTransform.tx).to.equal(25); - expect(child.worldTransform.ty).to.equal(20); + expect(child.worldTransform.tx).toEqual(25); + expect(child.worldTransform.ty).toEqual(20); const cacheParent = child.enableTempParent(); child.updateTransform(); child.disableTempParent(cacheParent); - expect(cacheParent).to.equal(container); - expect(child.parent).to.equal(container); - expect(child.worldTransform.tx).to.equal(15); - expect(child.worldTransform.ty).to.equal(10); + expect(cacheParent).toEqual(container); + expect(child.parent).toEqual(container); + expect(child.worldTransform.tx).toEqual(15); + expect(child.worldTransform.ty).toEqual(10); child.updateTransform(); - expect(child.worldTransform.tx).to.equal(25); - expect(child.worldTransform.ty).to.equal(20); + expect(child.worldTransform.tx).toEqual(25); + expect(child.worldTransform.ty).toEqual(20); }); }); - describe('mask', function () + describe('mask', () => { it('should set isMask and renderable properties correctly even if the same mask is used by multiple objects', - function () + () => { + // @ts-expect-error - instantiating DisplayOBject const mask1 = new DisplayObject(); + // @ts-expect-error - instantiating DisplayOBject const mask2 = new DisplayObject(); const container1 = new Container(); const container2 = new Container(); - expect(mask1.isMask).to.be.false; - expect(mask1.renderable).to.be.true; - expect(mask2.isMask).to.be.false; - expect(mask2.renderable).to.be.true; + expect(mask1.isMask).toBe(false); + expect(mask1.renderable).toBe(true); + expect(mask2.isMask).toBe(false); + expect(mask2.renderable).toBe(true); container1.mask = mask1; - expect(mask1.isMask).to.be.true; - expect(mask1.renderable).to.be.false; - expect(mask2.isMask).to.be.false; - expect(mask2.renderable).to.be.true; + expect(mask1.isMask).toBe(true); + expect(mask1.renderable).toBe(false); + expect(mask2.isMask).toBe(false); + expect(mask2.renderable).toBe(true); container1.mask = mask1; - expect(mask1.isMask).to.be.true; - expect(mask1.renderable).to.be.false; - expect(mask2.isMask).to.be.false; - expect(mask2.renderable).to.be.true; + expect(mask1.isMask).toBe(true); + expect(mask1.renderable).toBe(false); + expect(mask2.isMask).toBe(false); + expect(mask2.renderable).toBe(true); container2.mask = mask1; - expect(mask1.isMask).to.be.true; - expect(mask2.isMask).to.be.false; - expect(mask1.renderable).to.be.false; - expect(mask2.renderable).to.be.true; + expect(mask1.isMask).toBe(true); + expect(mask2.isMask).toBe(false); + expect(mask1.renderable).toBe(false); + expect(mask2.renderable).toBe(true); container1.mask = mask2; - expect(mask1.isMask).to.be.true; - expect(mask1.renderable).to.be.false; - expect(mask2.isMask).to.be.true; - expect(mask2.renderable).to.be.false; + expect(mask1.isMask).toBe(true); + expect(mask1.renderable).toBe(false); + expect(mask2.isMask).toBe(true); + expect(mask2.renderable).toBe(false); container2.mask = mask2; - expect(mask1.isMask).to.be.false; - expect(mask1.renderable).to.be.true; - expect(mask2.isMask).to.be.true; - expect(mask2.renderable).to.be.false; + expect(mask1.isMask).toBe(false); + expect(mask1.renderable).toBe(true); + expect(mask2.isMask).toBe(true); + expect(mask2.renderable).toBe(false); container1.mask = null; - expect(mask1.isMask).to.be.false; - expect(mask1.renderable).to.be.true; - expect(mask2.isMask).to.be.true; - expect(mask2.renderable).to.be.false; + expect(mask1.isMask).toBe(false); + expect(mask1.renderable).toBe(true); + expect(mask2.isMask).toBe(true); + expect(mask2.renderable).toBe(false); container2.mask = null; - expect(mask1.isMask).to.be.false; - expect(mask1.renderable).to.be.true; - expect(mask2.isMask).to.be.false; - expect(mask2.renderable).to.be.true; + expect(mask1.isMask).toBe(false); + expect(mask1.renderable).toBe(true); + expect(mask2.isMask).toBe(false); + expect(mask2.renderable).toBe(true); container1.mask = mask1; - expect(mask1.isMask).to.be.true; - expect(mask1.renderable).to.be.false; + expect(mask1.isMask).toBe(true); + expect(mask1.renderable).toBe(false); container1.destroy(); - expect(mask1.isMask).to.be.false; - expect(mask1.renderable).to.be.true; + expect(mask1.isMask).toBe(false); + expect(mask1.renderable).toBe(true); } ); }); - describe('remove', function () + describe('remove', () => { - it('should trigger removed listeners', function () + it('should trigger removed listeners', () => { - const listener = sinon.spy(); + const listener = jest.fn(); + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); const container = new Container(); @@ -236,20 +245,21 @@ describe('DisplayObject', function () container.addChild(child); container.removeChild(child); - expect(listener.calledOnce).to.be.true; + expect(listener).toBeCalledTimes(1); container.addChild(child); child.destroy(); - expect(listener.calledTwice).to.be.true; + expect(listener).toBeCalledTimes(2); }); }); - describe('destroy', function () + describe('destroy', () => { - it('should trigger destroyed listeners', function () + it('should trigger destroyed listeners', () => { - const listener = sinon.spy(); + const listener = jest.fn(); + // @ts-expect-error - instantiating DisplayOBject const child = new DisplayObject(); const container = new Container(); @@ -258,12 +268,37 @@ describe('DisplayObject', function () container.addChild(child); container.removeChild(child); - expect(listener.notCalled).to.be.true; + expect(listener).not.toBeCalled(); container.addChild(child); child.destroy(); - expect(listener.calledOnce).to.be.true; + expect(listener).toBeCalledTimes(1); + }); + + it('should trigger destroyed listeners once destruction is complete', () => + { + let listenerCallCount = 0; + // @ts-expect-error - instantiating DisplayOBject + const child = new DisplayObject(); + const container = new Container(); + + child.on('destroyed', () => + { + listenerCallCount++; + expect(child.destroyed).toBe(true); + expect(child.parent).toBeNull(); + }); + + container.addChild(child); + container.removeChild(child); + + expect(listenerCallCount).toEqual(0); + + container.addChild(child); + child.destroy(); + + expect(listenerCallCount).toEqual(1); }); }); }); diff --git a/packages/display/test/toGlobal.tests.ts b/packages/display/test/toGlobal.tests.ts index ca2b71a40e7..6af80d591ac 100644 --- a/packages/display/test/toGlobal.tests.ts +++ b/packages/display/test/toGlobal.tests.ts @@ -1,10 +1,9 @@ import { Container } from '@pixi/display'; -import { Point } from '@pixi/math'; -import { expect } from 'chai'; +import { Point } from '@pixi/core'; -describe('toGlobal', function () +describe('toGlobal', () => { - it('should return correct global cordinates of a point from within a displayObject', function () + it('should return correct global cordinates of a point from within a displayObject', () => { const parent = new Container(); @@ -16,8 +15,8 @@ describe('toGlobal', function () let globalPoint = container.toGlobal(point); - expect(globalPoint.x).to.equal(100); - expect(globalPoint.y).to.equal(100); + expect(globalPoint.x).toEqual(100); + expect(globalPoint.y).toEqual(100); container.position.x = 20; container.position.y = 20; @@ -27,7 +26,7 @@ describe('toGlobal', function () globalPoint = container.toGlobal(point); - expect(globalPoint.x).to.equal(220); - expect(globalPoint.y).to.equal(220); + expect(globalPoint.x).toEqual(220); + expect(globalPoint.y).toEqual(220); }); }); diff --git a/packages/display/test/toLocal.tests.ts b/packages/display/test/toLocal.tests.ts index 91cffc27bbc..bd7793a1074 100644 --- a/packages/display/test/toLocal.tests.ts +++ b/packages/display/test/toLocal.tests.ts @@ -1,10 +1,9 @@ import { Container } from '@pixi/display'; -import { Point } from '@pixi/math'; -import { expect } from 'chai'; +import { Point } from '@pixi/core'; -describe('toLocal', function () +describe('toLocal', () => { - it('should return correct local cordinates of a displayObject', function () + it('should return correct local cordinates of a displayObject', () => { const parent = new Container(); @@ -16,8 +15,8 @@ describe('toLocal', function () let localPoint = container.toLocal(point); - expect(localPoint.x).to.equal(100); - expect(localPoint.y).to.equal(100); + expect(localPoint.x).toEqual(100); + expect(localPoint.y).toEqual(100); container.position.x = 20; container.position.y = 20; @@ -27,11 +26,11 @@ describe('toLocal', function () localPoint = container.toLocal(point); - expect(localPoint.x).to.equal(40); - expect(localPoint.y).to.equal(40); + expect(localPoint.x).toEqual(40); + expect(localPoint.y).toEqual(40); }); - it('should map the correct local cordinates of a displayObject to another', function () + it('should map the correct local cordinates of a displayObject to another', () => { const parent = new Container(); @@ -51,7 +50,7 @@ describe('toLocal', function () const localPoint = container.toLocal(point, container2); - expect(localPoint.x).to.equal(100); - expect(localPoint.y).to.equal(100); + expect(localPoint.x).toEqual(100); + expect(localPoint.y).toEqual(100); }); }); diff --git a/packages/events/README.md b/packages/events/README.md index 16959b157e4..5adbc8ea0f1 100644 --- a/packages/events/README.md +++ b/packages/events/README.md @@ -1,4 +1,4 @@ -# @pixi/events +# @pixi/events This packages implements the Federated Events API, the plumbing behind the propagation of UI events into the PixiJS scene graph. @@ -11,37 +11,6 @@ npm install @pixi/events ## Usage -```ts -import { Renderer } from '@pixi/core'; -import { Application } from '@pixi/app'; -import { EventSystem } from '@pixi/events'; - -// If you are using the pixi.js/pixi.js-legacy bundles, you'll need to remove the interaction -// plugin. This is not needed when using the scoped (@pixi/) packages directly. -delete Renderer.__plugins.interaction; - -const app = new PIXI.Application(); -const { renderer } = app; - -document.body.appendChild(app.view); - -// Install the EventSystem -renderer.addSystem(EventSystem, 'events'); - -// Add a click listener! -stage.addEventListener('click', function handleClick() -{ - console.log('Hello world!'); -}); - -// Render stage so that it becomes the root target for UI events -renderer.render(stage); - -// Dispatch a synthetic event on the canvas to test it. -renderer.view.dispatchEvent(new PointerEvent('click', { - pointerType: 'mouse', - clientX: 1, - clientY: 1, - isPrimary: true, -})); +```js +import '@pixi/events'; ``` diff --git a/packages/events/global.d.ts b/packages/events/global.d.ts index 75d2fa4dff2..786f889e4a8 100644 --- a/packages/events/global.d.ts +++ b/packages/events/global.d.ts @@ -6,4 +6,19 @@ declare namespace GlobalMixins { } + + interface IRenderer + { + readonly events: import('@pixi/events').EventSystem; + } + + interface Renderer + { + readonly events: import('@pixi/events').EventSystem; + } + + interface CanvasRenderer + { + readonly events: import('@pixi/events').EventSystem; + } } diff --git a/packages/events/package.json b/packages/events/package.json index 1a8ec894916..8850eee4dc0 100644 --- a/packages/events/package.json +++ b/packages/events/package.json @@ -1,10 +1,22 @@ { "name": "@pixi/events", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/events.js", - "module": "dist/esm/events.js", - "bundle": "dist/browser/events.js", - "description": "UI events for scene graphs", + "module": "dist/esm/events.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/events.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/events.js" + } + } + }, + "description": "Federated Events API, the plumbing behind the propagation of UI events into the PixiJS scene graph.", "keywords": [ "interaction", "UI", @@ -17,7 +29,6 @@ "homepage": "https://github.com/pixijs/pixi.js#readme", "license": "MIT", "files": [ - "lib", "dist", "*.d.ts" ], @@ -31,9 +42,8 @@ "bugs": { "url": "https://github.com/pixijs/pixi.js/issues" }, - "peerDependencies": { - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/events/src/EventBoundary.ts b/packages/events/src/EventBoundary.ts index d9b0466dfa4..3535afc23e0 100644 --- a/packages/events/src/EventBoundary.ts +++ b/packages/events/src/EventBoundary.ts @@ -1,8 +1,7 @@ -import { EventEmitter } from '@pixi/utils'; import { FederatedMouseEvent } from './FederatedMouseEvent'; import { FederatedPointerEvent } from './FederatedPointerEvent'; import { FederatedWheelEvent } from './FederatedWheelEvent'; -import { Point } from '@pixi/math'; +import { Point, utils } from '@pixi/core'; import type { Cursor, FederatedEventTarget } from './FederatedEventTarget'; import type { DisplayObject } from '@pixi/display'; @@ -30,11 +29,10 @@ const tempLocalMapping = new Point(); * }; * overTargets: FederatedEventTarget[]; * ``` - * * @typedef {object} TrackingData * @property {Record.} pressTargetsByButton - The pressed display objects' * propagation paths by each button of the pointer. - * @property {Record.} clicksByButton - Holds clicking data for each button of the pointer. + * @property {Record.} clicksByButton - Holds clicking data for each button of the pointer. * @property {PIXI.DisplayObject[]} overTargets - The DisplayObject propagation path over which the pointer is hovering. * @memberof PIXI */ @@ -54,12 +52,11 @@ type TrackingData = { /** * Internal storage of event listeners in EventEmitter. - * * @ignore */ type EmitterListeners = Record - | { fn(...args: any[]): any, context: any } +| Array<{ fn(...args: any[]): any, context: any }> +| { fn(...args: any[]): any, context: any } >; /** @@ -116,7 +113,6 @@ type EmitterListeners = Record = { @@ -176,7 +168,6 @@ export class EventBoundary /** * The event pool maps event constructors to an free pool of instances of those specific events. - * * @see PIXI.EventBoundary#allocateEvent * @see PIXI.EventBoundary#freeEvent */ @@ -219,7 +210,6 @@ export class EventBoundary * * To modify the semantics of existing events, the built-in mapping methods of EventBoundary should be overridden * instead. - * * @param type - The type of upstream event to map. * @param fn - The mapping method. The context of this function must be bound manually, if desired. */ @@ -237,7 +227,11 @@ export class EventBoundary this.mappingTable[type].sort((a, b) => a.priority - b.priority); } - /** Dispatches the given event */ + /** + * Dispatches the given event + * @param e + * @param type + */ public dispatchEvent(e: FederatedEvent, type?: string): void { e.propagationStopped = false; @@ -247,7 +241,10 @@ export class EventBoundary this.dispatch.emit(type || e.type, e); } - /** Maps the given upstream event through the event boundary and propagates it downstream. */ + /** + * Maps the given upstream event through the event boundary and propagates it downstream. + * @param e + */ public mapEvent(e: FederatedEvent): void { if (!this.rootTarget) @@ -274,6 +271,8 @@ export class EventBoundary * Finds the DisplayObject that is the target of a event at the given coordinates. * * The passed (x,y) coordinates are in the world space above this event boundary. + * @param x + * @param y */ public hitTest( x: number, @@ -294,8 +293,8 @@ export class EventBoundary /** * Propagate the passed event from from {@link EventBoundary.rootTarget this.rootTarget} to its * target {@code e.target}. - * * @param e - The event to propagate. + * @param type */ public propagate(e: FederatedEvent, type?: string): void { @@ -344,9 +343,9 @@ export class EventBoundary * Emits the event {@link e} to all display objects. The event is propagated in the bubbling phase always. * * This is used in the `pointermove` legacy mode. - * * @param e - The emitted event. * @param type - The listeners to notify. + * @param target */ public all(e: FederatedEvent, type?: string, target: FederatedEventTarget = this.rootTarget): void { @@ -369,7 +368,6 @@ export class EventBoundary /** * Finds the propagation path from {@link PIXI.EventBoundary.rootTarget rootTarget} to the passed * {@code target}. The last element in the path is {@code target}. - * * @param target */ public propagationPath(target: FederatedEventTarget): FederatedEventTarget[] @@ -395,7 +393,6 @@ export class EventBoundary /** * Recursive implementation for {@link EventBoundary.hitTest hitTest}. - * * @param currentTarget - The DisplayObject that is to be hit tested. * @param interactive - Flags whether `currentTarget` or one of its parents are interactive. * @param location - The location that is being tested for overlap. @@ -404,7 +401,7 @@ export class EventBoundary * @param pruneFn - Callback that determiness whether the target and all of its children * cannot pass the hit test. It is used as a preliminary optimization to prune entire subtrees * of the scene graph. - * @return An array holding the hit testing target and all its ancestors in order. The first element + * @returns An array holding the hit testing target and all its ancestors in order. The first element * is the target itself and the last is {@link EventBoundary.rootTarget rootTarget}. This is the opposite * order w.r.t. the propagation path. If no hit testing target is found, null is returned. */ @@ -482,7 +479,6 @@ export class EventBoundary * * {@link EventBoundary}'s implementation uses the {@link PIXI.DisplayObject.hitArea hitArea} * and {@link PIXI.DisplayObject._mask} for pruning. - * * @param displayObject * @param location */ @@ -500,9 +496,10 @@ export class EventBoundary if (displayObject._mask) { - const mask = displayObject._mask as any; + const maskObject = ((displayObject._mask as any).isMaskData + ? (displayObject._mask as any).maskObject : displayObject._mask); - if (!(mask.containsPoint && mask.containsPoint(location))) + if (maskObject && !maskObject.containsPoint?.(location)) { return true; } @@ -513,10 +510,9 @@ export class EventBoundary /** * Checks whether the display object passes hit testing for the given location. - * * @param displayObject * @param location - * @return - Whether `displayObject` passes hit testing for `location`. + * @returns - Whether `displayObject` passes hit testing for `location`. */ protected hitTestFn(displayObject: DisplayObject, location: Point): boolean { @@ -538,8 +534,8 @@ export class EventBoundary /** * Notify all the listeners to the event's `currentTarget`. - * * @param e - The event passed to the target. + * @param type */ protected notifyTarget(e: FederatedEvent, type?: string): void { @@ -558,7 +554,6 @@ export class EventBoundary * Maps the upstream `pointerdown` events to a downstream `pointerdown` event. * * `touchstart`, `rightdown`, `mousedown` events are also dispatched for specific pointer types. - * * @param from */ protected mapPointerDown(from: FederatedEvent): void @@ -597,7 +592,6 @@ export class EventBoundary * * The tracking data for the specific pointer has an updated `overTarget`. `mouseout`, `mouseover`, * `mousemove`, and `touchmove` events are fired as well for specific pointer types. - * * @param from - The upstream `pointermove` event. */ protected mapPointerMove(from: FederatedEvent): void @@ -718,7 +712,6 @@ export class EventBoundary * Maps the upstream `pointerover` to downstream `pointerover` and `pointerenter` events, in that order. * * The tracking data for the specific pointer gets a new `overTarget`. - * * @param from - The upstream `pointerover` event. */ protected mapPointerOver(from: FederatedEvent): void @@ -763,7 +756,6 @@ export class EventBoundary * Maps the upstream `pointerout` to downstream `pointerout`, `pointerleave` events, in that order. * * The tracking data for the specific pointer is cleared of a `overTarget`. - * * @param from - The upstream `pointerout` event. */ protected mapPointerOut(from: FederatedEvent): void @@ -821,7 +813,6 @@ export class EventBoundary * ancestor of the `pointerdown` and `pointerup` targets, which is also the `click` event's target. `touchend`, * `rightup`, `mouseup`, `touchendoutside`, `rightupoutside`, `mouseupoutside`, and `tap` are fired as well for * specific pointer types. - * * @param from - The upstream `pointerup` event. */ protected mapPointerUp(from: FederatedEvent): void @@ -929,10 +920,8 @@ export class EventBoundary { this.dispatchEvent(clickEvent, 'tap'); } - else - { - this.dispatchEvent(clickEvent, 'pointertap'); - } + + this.dispatchEvent(clickEvent, 'pointertap'); this.freeEvent(clickEvent); } @@ -949,7 +938,6 @@ export class EventBoundary * * `touchendoutside`, `mouseupoutside`, and `rightupoutside` events are fired as well for specific pointer * types. The tracking data for the specific pointer is cleared of a `pressTarget`. - * * @param from - The upstream `pointerupoutside` event. */ protected mapPointerUpOutside(from: FederatedEvent): void @@ -995,7 +983,6 @@ export class EventBoundary /** * Maps the upstream `wheel` event to a downstream `wheel` event. - * * @param from - The upstream `wheel` event. */ protected mapWheel(from: FederatedEvent): void @@ -1018,9 +1005,8 @@ export class EventBoundary * * This is used to find the correct `pointerup` and `pointerout` target in the case that the original `pointerdown` * or `pointerover` target was unmounted from the scene graph. - * * @param propagationPath - The propagation path was valid in the past. - * @return - The most specific event-target still mounted at the same location in the scene graph. + * @returns - The most specific event-target still mounted at the same location in the scene graph. */ protected findMountedTarget(propagationPath: FederatedEventTarget[]): FederatedEventTarget { @@ -1052,7 +1038,6 @@ export class EventBoundary * Creates an event whose {@code originalEvent} is {@code from}, with an optional `type` and `target` override. * * The event is allocated using {@link PIXI.EventBoundary#allocateEvent this.allocateEvent}. - * * @param from - The {@code originalEvent} for the returned event. * @param [type=from.type] - The type of the returned event. * @param target - The target of the returned event. @@ -1085,7 +1070,6 @@ export class EventBoundary * Creates a wheel event whose {@code originalEvent} is {@code from}. * * The event is allocated using {@link PIXI.EventBoundary#allocateEvent this.allocateEvent}. - * * @param from - The upstream wheel event. */ protected createWheelEvent(from: FederatedWheelEvent): FederatedWheelEvent @@ -1107,7 +1091,6 @@ export class EventBoundary * Clones the event {@code from}, with an optional {@code type} override. * * The event is allocated using {@link PIXI.EventBoundary#allocateEvent this.allocateEvent}. - * * @param from - The event to clone. * @param [type=from.type] - The type of the returned event. */ @@ -1138,7 +1121,6 @@ export class EventBoundary * + deltaX * + deltaY * + deltaZ - * * @param from * @param to */ @@ -1163,7 +1145,6 @@ export class EventBoundary * + tangentialPressure * + tiltX * + tiltY - * * @param from * @param to */ @@ -1201,7 +1182,6 @@ export class EventBoundary * + y * + screen * + global - * * @param from * @param to */ @@ -1229,7 +1209,6 @@ export class EventBoundary * + srcElement * + timeStamp * + type - * * @param from - The event to copy data from. * @param to - The event to copy data into. */ @@ -1248,7 +1227,7 @@ export class EventBoundary /** * @param id - The pointer ID. - * @return The tracking data stored for the given pointer. If no data exists, a blank + * @returns The tracking data stored for the given pointer. If no data exists, a blank * state will be created. */ protected trackingData(id: number): TrackingData @@ -1270,7 +1249,6 @@ export class EventBoundary * * This allocation is constructor-agnostic, as long as it only takes one argument - this event * boundary. - * * @param constructor - The event's constructor. */ protected allocateEvent( @@ -1301,7 +1279,6 @@ export class EventBoundary * It is also advised that events not allocated from {@link PIXI.EventBoundary#allocateEvent this.allocateEvent} * not be freed. This is because of the possibility that the same event is freed twice, which can cause * it to be allocated twice & result in overwriting. - * * @param event - The event to be freed. * @throws Error if the event is managed by another event boundary. */ @@ -1322,7 +1299,6 @@ export class EventBoundary /** * Similar to {@link EventEmitter.emit}, except it stops if the `propagationImmediatelyStopped` flag * is set on the event. - * * @param e - The event to call each listener with. * @param type - The event key. */ @@ -1354,7 +1330,6 @@ export class EventBoundary * object. DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mousedown * @param {PIXI.FederatedPointerEvent} event - The mousedown event. */ @@ -1363,7 +1338,6 @@ export class EventBoundary * Capture phase equivalent of {@code mousedown}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mousedowncapture * @param {PIXI.FederatedPointerEvent} event - The capture phase mousedown. */ @@ -1373,7 +1347,6 @@ export class EventBoundary * on the display object. DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightdown * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1382,7 +1355,6 @@ export class EventBoundary * Capture phase equivalent of {@code rightdown}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightdowncapture * @param {PIXI.FederatedPointerEvent} event - The rightdowncapture event. */ @@ -1392,7 +1364,6 @@ export class EventBoundary * object. DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseup * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1401,7 +1372,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseup}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseupcature * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1411,7 +1381,6 @@ export class EventBoundary * over the display object. DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightup * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1420,7 +1389,6 @@ export class EventBoundary * Capture phase equivalent of {@code rightup}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightupcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1437,7 +1405,6 @@ export class EventBoundary * window of each other upto the current click. For example, it will be {@code 2} for a double click. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#click * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1446,7 +1413,6 @@ export class EventBoundary * Capture phase equivalent of {@code click}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#clickcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1458,7 +1424,6 @@ export class EventBoundary * This event follows the semantics of {@code click}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightclick * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1467,7 +1432,6 @@ export class EventBoundary * Capture phase equivalent of {@code rightclick}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightclickcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1483,7 +1447,6 @@ export class EventBoundary * and {@code pointerup} events, i.e. the target of the {@code click} event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseupoutside * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1492,7 +1455,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseupoutside}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseupoutsidecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1504,7 +1466,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightupoutside * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1513,7 +1474,6 @@ export class EventBoundary * Capture phase equivalent of {@code rightupoutside}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#rightupoutsidecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1523,7 +1483,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mousemove * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1532,7 +1491,6 @@ export class EventBoundary * Capture phase equivalent of {@code mousemove}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mousemovecature * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1542,7 +1500,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseover * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1551,7 +1508,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseover}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseovercapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1560,7 +1516,6 @@ export class EventBoundary * Fired when the mouse pointer is moved over a DisplayObject and its descendant's hit testing boundaries. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseenter * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1569,7 +1524,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseenter} * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseentercapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1582,7 +1536,6 @@ export class EventBoundary * a {@code mouseover} event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseout * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1591,7 +1544,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseout}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseoutcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1600,7 +1552,6 @@ export class EventBoundary * Fired when the mouse pointer exits a DisplayObject and its descendants. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseleave * @param {PIXI.FederatedPointerEvent} event */ @@ -1609,7 +1560,6 @@ export class EventBoundary * Capture phase equivalent of {@code mouseleave}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#mouseleavecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1619,7 +1569,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerdown * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1628,7 +1577,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerdown}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerdowncapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1638,7 +1586,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerup * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1647,7 +1594,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerup}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerupcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1657,7 +1603,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointercancel * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1666,7 +1611,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointercancel}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointercancelcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1676,7 +1620,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointertap * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1685,7 +1628,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointertap}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointertapcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1700,7 +1642,6 @@ export class EventBoundary * and {@code pointerup} events, i.e. the target of the {@code click} event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerupoutside * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1709,7 +1650,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerupoutside}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerupoutsidecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1719,7 +1659,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointermove * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1728,7 +1667,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointermove}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointermovecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1738,7 +1676,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerover * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1747,7 +1684,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerover}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerovercapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1756,7 +1692,6 @@ export class EventBoundary * Fired when the pointer is moved over a DisplayObject and its descendant's hit testing boundaries. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerenter * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1765,7 +1700,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerenter} * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerentercapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1775,7 +1709,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerout * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1784,7 +1717,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerout}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointeroutcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1795,7 +1727,6 @@ export class EventBoundary * This event notifies only the target and does not bubble. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerleave * @param {PIXI.FederatedPointerEvent} event - The `pointerleave` event. */ @@ -1804,7 +1735,6 @@ export class EventBoundary * Capture phase equivalent of {@code pointerleave}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#pointerleavecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1814,7 +1744,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchstart * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1823,7 +1752,6 @@ export class EventBoundary * Capture phase equivalent of {@code touchstart}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchstartcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1833,7 +1761,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchend * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1842,7 +1769,6 @@ export class EventBoundary * Capture phase equivalent of {@code touchend}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchendcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1852,7 +1778,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchcancel * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1861,7 +1786,6 @@ export class EventBoundary * Capture phase equivalent of {@code touchcancel}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchcancelcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1871,7 +1795,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#tap * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1880,7 +1803,6 @@ export class EventBoundary * Capture phase equivalent of {@code tap}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#tapcapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1891,7 +1813,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchendoutside * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1900,7 +1821,6 @@ export class EventBoundary * Capture phase equivalent of {@code touchendoutside}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchendoutsidecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1910,7 +1830,6 @@ export class EventBoundary * DisplayObject's `interactive` property must be set to `true` to fire event. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchmove * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1919,7 +1838,6 @@ export class EventBoundary * Capture phase equivalent of {@code touchmove}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#touchmovecapture * @param {PIXI.FederatedPointerEvent} event - Event */ @@ -1928,7 +1846,6 @@ export class EventBoundary * Fired when a the user scrolls with the mouse cursor over a DisplayObject. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#wheel * @type {PIXI.FederatedWheelEvent} */ @@ -1937,7 +1854,6 @@ export class EventBoundary * Capture phase equivalent of {@code wheel}. * * These events are propagating from the {@link PIXI.EventSystem EventSystem} in @pixi/events. - * * @event PIXI.DisplayObject#wheelcapture * @type {PIXI.FederatedWheelEvent} */ diff --git a/packages/events/src/EventSystem.ts b/packages/events/src/EventSystem.ts index 3b3db9aadfa..6558b7c3b35 100644 --- a/packages/events/src/EventSystem.ts +++ b/packages/events/src/EventSystem.ts @@ -1,11 +1,11 @@ import { EventBoundary } from './EventBoundary'; -import { FederatedMouseEvent } from './FederatedMouseEvent'; +import type { FederatedMouseEvent } from './FederatedMouseEvent'; import { FederatedPointerEvent } from './FederatedPointerEvent'; import { FederatedWheelEvent } from './FederatedWheelEvent'; +import { extensions, ExtensionType } from '@pixi/core'; -import type { IRenderableObject } from '@pixi/core'; import type { DisplayObject } from '@pixi/display'; -import type { IPointData } from '@pixi/math'; +import type { IRenderableObject, ExtensionMetadata, IPointData } from '@pixi/core'; const MOUSE_POINTER_ID = 1; const TOUCH_TO_POINTER: Record = { @@ -18,7 +18,7 @@ const TOUCH_TO_POINTER: Record = { interface Renderer { - _lastObjectRendered: IRenderableObject; + lastObjectRendered: IRenderableObject; view: HTMLCanvasElement; resolution: number; plugins: Record; @@ -26,11 +26,19 @@ interface Renderer /** * The system for handling UI events. - * * @memberof PIXI */ export class EventSystem { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'events', + type: [ + ExtensionType.RendererSystem, + ExtensionType.CanvasRendererSystem + ], + }; + /** * The {@link PIXI.EventBoundary} for the stage. * @@ -43,16 +51,10 @@ export class EventSystem */ public readonly rootBoundary: EventBoundary; - /** - * Does the device support touch events - * https://www.w3.org/TR/touch-events/ - */ + /** Does the device support touch events https://www.w3.org/TR/touch-events/ */ public readonly supportsTouchEvents = 'ontouchstart' in globalThis; - /** - * Does the device support pointer events - * https://www.w3.org/Submission/pointer-events/ - */ + /** Does the device support pointer events https://www.w3.org/Submission/pointer-events/ */ public readonly supportsPointerEvents = !!globalThis.PointerEvent; /** @@ -60,7 +62,6 @@ export class EventSystem * Does not apply to pointer events for backwards compatibility * preventDefault on pointer events stops mouse events from firing * Thus, for every pointer event, there will always be either a mouse of touch event alongside it. - * * @default true */ public autoPreventDefault: boolean; @@ -70,8 +71,7 @@ export class EventSystem * values, objects are handled as dictionaries of CSS values for {@code domElement}, * and functions are called instead of changing the CSS. * Default CSS cursor values are provided for 'default' and 'pointer' modes. - * - * @member {Object. void) | CSSStyleDeclaration>} + * @member {Object void) | CSSStyleDeclaration>} */ public cursorStyles: Record void) | CSSStyleDeclaration>; @@ -79,16 +79,12 @@ export class EventSystem * The DOM element to which the root event listeners are bound. This is automatically set to * the renderer's {@link PIXI.Renderer#view view}. */ - public domElement: HTMLElement; + public domElement: HTMLElement = null; - /** - * The resolution used to convert between the DOM client space into world space. - */ + /** The resolution used to convert between the DOM client space into world space. */ public resolution = 1; - /** - * The renderer managing this {@link EventSystem}. - */ + /** The renderer managing this {@link EventSystem}. */ public renderer: Renderer; private currentCursor: string; @@ -101,11 +97,6 @@ export class EventSystem */ constructor(renderer: Renderer) { - if (renderer.plugins.interaction) - { - throw new Error('EventSystem cannot initialize with the InteractionManager installed!'); - } - this.renderer = renderer; this.rootBoundary = new EventBoundary(null); @@ -119,21 +110,27 @@ export class EventSystem default: 'inherit', pointer: 'pointer', }; - this.domElement = renderer.view; this.onPointerDown = this.onPointerDown.bind(this); this.onPointerMove = this.onPointerMove.bind(this); this.onPointerUp = this.onPointerUp.bind(this); this.onPointerOverOut = this.onPointerOverOut.bind(this); this.onWheel = this.onWheel.bind(this); - - this.setTargetElement(this.domElement); - this.resolution = this.renderer.resolution; } /** - * Destroys all event listeners and detaches the renderer. + * Runner init called, view is available at this point. + * @ignore */ + init(): void + { + const { view, resolution } = this.renderer; + + this.setTargetElement(view); + this.resolution = resolution; + } + + /** Destroys all event listeners and detaches the renderer. */ destroy(): void { this.setTargetElement(null); @@ -142,7 +139,6 @@ export class EventSystem /** * Sets the current cursor mode, handling any callbacks or CSS style changes. - * * @param mode - cursor mode, a key from the cursorStyles dictionary */ public setCursor(mode: string): void @@ -200,12 +196,11 @@ export class EventSystem /** * Event handler for pointer down events on {@link PIXI.EventSystem#domElement this.domElement}. - * * @param nativeEvent - The native mouse/pointer/touch event. */ private onPointerDown(nativeEvent: MouseEvent | PointerEvent | TouchEvent): void { - this.rootBoundary.rootTarget = this.renderer._lastObjectRendered as DisplayObject; + this.rootBoundary.rootTarget = this.renderer.lastObjectRendered as DisplayObject; // if we support touch events, then only use those for touch events, not pointer events if (this.supportsTouchEvents && (nativeEvent as PointerEvent).pointerType === 'touch') return; @@ -243,12 +238,11 @@ export class EventSystem /** * Event handler for pointer move events on on {@link PIXI.EventSystem#domElement this.domElement}. - * * @param nativeEvent - The native mouse/pointer/touch events. */ private onPointerMove(nativeEvent: MouseEvent | PointerEvent | TouchEvent): void { - this.rootBoundary.rootTarget = this.renderer._lastObjectRendered as DisplayObject; + this.rootBoundary.rootTarget = this.renderer.lastObjectRendered as DisplayObject; // if we support touch events, then only use those for touch events, not pointer events if (this.supportsTouchEvents && (nativeEvent as PointerEvent).pointerType === 'touch') return; @@ -267,17 +261,24 @@ export class EventSystem /** * Event handler for pointer up events on {@link PIXI.EventSystem#domElement this.domElement}. - * * @param nativeEvent - The native mouse/pointer/touch event. */ private onPointerUp(nativeEvent: MouseEvent | PointerEvent | TouchEvent): void { - this.rootBoundary.rootTarget = this.renderer._lastObjectRendered as DisplayObject; + this.rootBoundary.rootTarget = this.renderer.lastObjectRendered as DisplayObject; // if we support touch events, then only use those for touch events, not pointer events if (this.supportsTouchEvents && (nativeEvent as PointerEvent).pointerType === 'touch') return; - const outside = nativeEvent.target !== this.domElement ? 'outside' : ''; + let target = nativeEvent.target; + + // if in shadow DOM use composedPath to access target + if (nativeEvent.composedPath && nativeEvent.composedPath().length > 0) + { + target = nativeEvent.composedPath()[0]; + } + + const outside = target !== this.domElement ? 'outside' : ''; const normalizedEvents = this.normalizeToPointerData(nativeEvent); for (let i = 0, j = normalizedEvents.length; i < j; i++) @@ -294,12 +295,11 @@ export class EventSystem /** * Event handler for pointer over & out events on {@link PIXI.EventSystem#domElement this.domElement}. - * * @param nativeEvent - The native mouse/pointer/touch event. */ private onPointerOverOut(nativeEvent: MouseEvent | PointerEvent | TouchEvent): void { - this.rootBoundary.rootTarget = this.renderer._lastObjectRendered as DisplayObject; + this.rootBoundary.rootTarget = this.renderer.lastObjectRendered as DisplayObject; // if we support touch events, then only use those for touch events, not pointer events if (this.supportsTouchEvents && (nativeEvent as PointerEvent).pointerType === 'touch') return; @@ -318,14 +318,13 @@ export class EventSystem /** * Passive handler for `wheel` events on {@link EventSystem.domElement this.domElement}. - * * @param nativeEvent - The native wheel event. */ protected onWheel(nativeEvent: WheelEvent): void { const wheelEvent = this.normalizeWheelEvent(nativeEvent); - this.rootBoundary.rootTarget = this.renderer._lastObjectRendered as DisplayObject; + this.rootBoundary.rootTarget = this.renderer.lastObjectRendered as DisplayObject; this.rootBoundary.mapEvent(wheelEvent); } @@ -333,7 +332,6 @@ export class EventSystem * Sets the {@link PIXI.EventSystem#domElement domElement} and binds event listeners. * * To deregister the current DOM element without setting a new one, pass {@code null}. - * * @param element - The new DOM element. */ public setTargetElement(element: HTMLElement): void @@ -343,9 +341,7 @@ export class EventSystem this.addEvents(); } - /** - * Register event listeners on {@link PIXI.Renderer#domElement this.domElement}. - */ + /** Register event listeners on {@link PIXI.Renderer#domElement this.domElement}. */ private addEvents(): void { if (this.eventsAdded || !this.domElement) @@ -355,7 +351,7 @@ export class EventSystem const style = this.domElement.style as CrossCSSStyleDeclaration; - if (globalThis.navigator.msPointerEnabled) + if ((globalThis.navigator as any).msPointerEnabled) { style.msContentZooming = 'none'; style.msTouchAction = 'none'; @@ -409,9 +405,7 @@ export class EventSystem this.eventsAdded = true; } - /** - * Unregister event listeners on {@link PIXI.EventSystem#domElement this.domElement}. - */ + /** Unregister event listeners on {@link PIXI.EventSystem#domElement this.domElement}. */ private removeEvents(): void { if (!this.eventsAdded || !this.domElement) @@ -421,7 +415,7 @@ export class EventSystem const style = this.domElement.style as CrossCSSStyleDeclaration; - if (globalThis.navigator.msPointerEnabled) + if ((globalThis.navigator as any).msPointerEnabled) { style.msContentZooming = ''; style.msTouchAction = ''; @@ -467,7 +461,6 @@ export class EventSystem * Maps x and y coords from a DOM object and maps them correctly to the PixiJS view. The * resulting value is stored in the point. This takes into account the fact that the DOM * element could be scaled and positioned anywhere on the screen. - * * @param {PIXI.IPointData} point - the point that the result will be stored in * @param {number} x - the x coord of the position to map * @param {number} y - the y coord of the position to map @@ -501,12 +494,11 @@ export class EventSystem /** * Ensures that the original event object contains all data that a regular pointer event would have - * * @param event - The original event data from a touch or mouse event - * @return An array containing a single normalized pointer event, in the case of a pointer + * @returns An array containing a single normalized pointer event, in the case of a pointer * or mouse event, or a multiple normalized pointer events if there are multiple changed touches */ - private normalizeToPointerData(event: TouchEvent|MouseEvent|PointerEvent): PointerEvent[] + private normalizeToPointerData(event: TouchEvent | MouseEvent | PointerEvent): PointerEvent[] { const normalizedEvents = []; @@ -516,8 +508,8 @@ export class EventSystem { const touch = event.changedTouches[i] as PixiTouch; - if (typeof touch.button === 'undefined') touch.button = event.touches.length ? 1 : 0; - if (typeof touch.buttons === 'undefined') touch.buttons = event.touches.length ? 1 : 0; + if (typeof touch.button === 'undefined') touch.button = 0; + if (typeof touch.buttons === 'undefined') touch.buttons = 1; if (typeof touch.isPrimary === 'undefined') { touch.isPrimary = event.touches.length === 1 && event.type === 'touchstart'; @@ -580,9 +572,8 @@ export class EventSystem * * The returned {@link PIXI.FederatedWheelEvent} is a shared instance. It will not persist across * multiple native wheel events. - * * @param nativeEvent - The native wheel event that occurred on the canvas. - * @return A federated wheel event. + * @returns A federated wheel event. */ protected normalizeWheelEvent(nativeEvent: WheelEvent): FederatedWheelEvent { @@ -607,7 +598,6 @@ export class EventSystem /** * Normalizes the {@code nativeEvent} into a federateed {@code FederatedPointerEvent}. - * * @param event * @param nativeEvent */ @@ -651,7 +641,6 @@ export class EventSystem /** * Transfers base & mouse event data from the {@code nativeEvent} to the federated event. - * * @param event * @param nativeEvent */ @@ -720,3 +709,5 @@ interface PixiTouch extends Touch isNormalized: boolean; type: string; } + +extensions.add(EventSystem); diff --git a/packages/events/src/FederatedEvent.ts b/packages/events/src/FederatedEvent.ts index b01782de1ae..71d75b44a36 100644 --- a/packages/events/src/FederatedEvent.ts +++ b/packages/events/src/FederatedEvent.ts @@ -1,11 +1,10 @@ -import { Point } from '@pixi/math'; +import { Point } from '@pixi/core'; import type { EventBoundary } from './EventBoundary'; import type { FederatedEventTarget } from './FederatedEventTarget'; /** * An DOM-compatible synthetic event implementation that is "forwarded" on behalf of an original * FederatedEvent or native {@link https://dom.spec.whatwg.org/#event Event}. - * * @memberof PIXI * @typeParam N - The type of native event held. */ @@ -14,7 +13,7 @@ export class FederatedEvent implements UIEvent /** Flags whether this event bubbles. This will take effect only if it is set before propagation. */ public bubbles = true; - /** @deprecated */ + /** @deprecated since 7.0.0 */ public cancelBubble = true; /** @@ -26,7 +25,6 @@ export class FederatedEvent implements UIEvent /** * Flag added for compatibility with DOM {@code Event}. It is not used in the Federated Events * API. - * * @see https://dom.spec.whatwg.org/#dom-event-composed */ public readonly composed = false; @@ -39,7 +37,6 @@ export class FederatedEvent implements UIEvent /** * The propagation phase. - * * @default {@link FederatedEvent.NONE} */ public eventPhase = FederatedEvent.prototype.NONE; @@ -47,10 +44,10 @@ export class FederatedEvent implements UIEvent /** Flags whether this is a user-trusted event */ public isTrusted: boolean; - /** @deprecated */ + /** @deprecated since 7.0.0 */ public returnValue: boolean; - /** @deprecated */ + /** @deprecated since 7.0.0 */ public srcElement: EventTarget; /** The event target that this will be dispatched to. */ @@ -88,14 +85,11 @@ export class FederatedEvent implements UIEvent /** * Not supported. - * @deprecated + * @deprecated since 7.0.0 */ public which: number; - /** - * The coordinates of the evnet relative to the nearest DOM layer. This is a non-standard - * property. - */ + /** The coordinates of the evnet relative to the nearest DOM layer. This is a non-standard property. */ public layer: Point = new Point(); /** @readonly */ @@ -104,9 +98,7 @@ export class FederatedEvent implements UIEvent /** @readonly */ get layerY(): number { return this.layer.y; } - /** - * The coordinates of the event relative to the DOM document. This is a non-standard property. - */ + /** The coordinates of the event relative to the DOM document. This is a non-standard property. */ public page: Point = new Point(); /** @readonly */ @@ -126,17 +118,14 @@ export class FederatedEvent implements UIEvent /** * Fallback for the deprecated {@link PIXI.InteractionEvent.data}. - * - * @deprecated + * @deprecated since 7.0.0 */ get data(): this { return this; } - /** - * The propagation path for this event. Alias for {@link EventBoundary.propagationPath}. - */ + /** The propagation path for this event. Alias for {@link EventBoundary.propagationPath}. */ composedPath(): FederatedEventTarget[] { // Find the propagation path if it isn't cached or if the target has changed since since @@ -150,17 +139,17 @@ export class FederatedEvent implements UIEvent } /** - * Unimplemented method included for implementing the DOM interface {@code Event}. It will throw - * an {@code Error}. + * Unimplemented method included for implementing the DOM interface {@code Event}. It will throw an {@code Error}. + * @param _type + * @param _bubbles + * @param _cancelable */ initEvent(_type: string, _bubbles?: boolean, _cancelable?: boolean): void { throw new Error('initEvent() is a legacy DOM API. It is not implemented in the Federated Events API.'); } - /** - * Prevent default behavior of PixiJS and the user agent. - */ + /** Prevent default behavior of PixiJS and the user agent. */ preventDefault(): void { if (this.nativeEvent instanceof Event && this.nativeEvent.cancelable) diff --git a/packages/events/src/FederatedEventTarget.ts b/packages/events/src/FederatedEventTarget.ts index 718f5e856d1..1340c32f406 100644 --- a/packages/events/src/FederatedEventTarget.ts +++ b/packages/events/src/FederatedEventTarget.ts @@ -1,56 +1,57 @@ import { DisplayObject } from '@pixi/display'; import { FederatedEvent } from './FederatedEvent'; -import type { EventEmitter } from '@pixi/utils'; +import type { utils } from '@pixi/core'; export type Cursor = 'auto' - | 'default' - | 'none' - | 'context-menu' - | 'help' - | 'pointer' - | 'progress' - | 'wait' - | 'cell' - | 'crosshair' - | 'text' - | 'vertical-text' - | 'alias' - | 'copy' - | 'move' - | 'no-drop' - | 'not-allowed' - | 'e-resize' - | 'n-resize' - | 'ne-resize' - | 'nw-resize' - | 's-resize' - | 'se-resize' - | 'sw-resize' - | 'w-resize' - | 'ns-resize' - | 'ew-resize' - | 'nesw-resize' - | 'col-resize' - | 'nwse-resize' - | 'row-resize' - | 'all-scroll' - | 'zoom-in' - | 'zoom-out' - | 'grab' - | 'grabbing'; +| 'default' +| 'none' +| 'context-menu' +| 'help' +| 'pointer' +| 'progress' +| 'wait' +| 'cell' +| 'crosshair' +| 'text' +| 'vertical-text' +| 'alias' +| 'copy' +| 'move' +| 'no-drop' +| 'not-allowed' +| 'e-resize' +| 'n-resize' +| 'ne-resize' +| 'nw-resize' +| 's-resize' +| 'se-resize' +| 'sw-resize' +| 'w-resize' +| 'ns-resize' +| 'ew-resize' +| 'nesw-resize' +| 'col-resize' +| 'nwse-resize' +| 'row-resize' +| 'all-scroll' +| 'zoom-in' +| 'zoom-out' +| 'grab' +| 'grabbing'; // @ignore - This is documented elsewhere. -export interface IHitArea { +export interface IHitArea +{ contains(x: number, y: number): boolean; } /** * Describes the shape for a {@link FederatedEvent}'s' `eventTarget`. - * * @memberof PIXI */ -export interface FederatedEventTarget extends EventEmitter, EventTarget { +export interface FederatedEventTarget extends utils.EventEmitter, EventTarget +{ /** The cursor preferred when the mouse pointer is hovering over. */ cursor: Cursor | string; @@ -63,10 +64,7 @@ export interface FederatedEventTarget extends EventEmitter, EventTarget { /** Whether this event target should fire UI events. */ interactive: boolean; - /** - * Whether this event target has any children that need UI events. This can be used optimize - * event propagation. - */ + /** Whether this event target has any children that need UI events. This can be used optimize event propagation. */ interactiveChildren: boolean; /** The hit-area specifies the area for which pointer events should be captured by this event target. */ @@ -74,13 +72,12 @@ export interface FederatedEventTarget extends EventEmitter, EventTarget { } export const FederatedDisplayObject: Omit< - FederatedEventTarget, - 'parent' | 'children' | keyof EventEmitter | 'cursor' +FederatedEventTarget, +'parent' | 'children' | keyof utils.EventEmitter | 'cursor' > = { /** * Enable interaction events for the DisplayObject. Touch, pointer and mouse * events will not be emitted unless `interactive` is set to `true`. - * * @example * const sprite = new PIXI.Sprite(texture); * sprite.interactive = true; @@ -94,7 +91,6 @@ export const FederatedDisplayObject: Omit< /** * Determines if the children to the displayObject can be clicked/touched * Setting this to false allows PixiJS to bypass a recursive `hitTest` function - * * @memberof PIXI.Container# */ interactiveChildren: true, @@ -102,7 +98,6 @@ export const FederatedDisplayObject: Omit< /** * Interaction shape. Children will be hit first, then this shape will be checked. * Setting this will cause this shape to be checked in hit tests rather than the displayObject's bounds. - * * @example * const sprite = new PIXI.Sprite(texture); * sprite.interactive = true; @@ -158,7 +153,7 @@ export const FederatedDisplayObject: Omit< type = capture ? `${type}capture` : type; listener = typeof listener === 'function' ? listener : listener.handleEvent; - (this as unknown as EventEmitter).on(type, listener, context); + (this as unknown as utils.EventEmitter).on(type, listener, context); }, /** @@ -183,7 +178,7 @@ export const FederatedDisplayObject: Omit< type = capture ? `${type}capture` : type; listener = typeof listener === 'function' ? listener : listener.handleEvent; - (this as unknown as EventEmitter).off(type, listener, context); + (this as unknown as utils.EventEmitter).off(type, listener, context); }, /** @@ -194,7 +189,7 @@ export const FederatedDisplayObject: Omit< * **IMPORTANT:** _Only_ available if using the `@pixi/events` package. * @memberof PIXI.DisplayObject * @param e - The event to dispatch. - * @return Whether the {@link PIXI.FederatedEvent.preventDefault preventDefault}() method was not invoked. + * @returns Whether the {@link PIXI.FederatedEvent.preventDefault preventDefault}() method was not invoked. * @example * // Reuse a click event! * button.dispatchEvent(clickEvent); diff --git a/packages/events/src/FederatedMouseEvent.ts b/packages/events/src/FederatedMouseEvent.ts index 928521f741d..7308859b092 100644 --- a/packages/events/src/FederatedMouseEvent.ts +++ b/packages/events/src/FederatedMouseEvent.ts @@ -1,13 +1,12 @@ import { FederatedEvent } from './FederatedEvent'; -import { Point } from '@pixi/math'; +import { Point } from '@pixi/core'; /** * A {@link PIXI.FederatedEvent} for mouse events. - * * @memberof PIXI */ export class FederatedMouseEvent extends FederatedEvent< - MouseEvent | PointerEvent | TouchEvent +MouseEvent | PointerEvent | TouchEvent > implements MouseEvent { /** Whether the "alt" key was pressed when this mouse event occurred. */ @@ -31,9 +30,7 @@ export class FederatedMouseEvent extends FederatedEvent< /** Whether the "shift" key was pressed when this mouse event occurred. */ shiftKey: boolean; - /** - * The coordinates of the mouse event relative to the canvas. - */ + /** The coordinates of the mouse event relative to the canvas. */ public client: Point = new Point(); /** @readonly */ @@ -44,26 +41,20 @@ export class FederatedMouseEvent extends FederatedEvent< /** * Alias for {@link FederatedMouseEvent.clientX this.clientX}. - * * @readonly */ get x(): number { return this.clientX; } /** * Alias for {@link FederatedMouseEvent.clientY this.clientY}. - * * @readonly */ get y(): number { return this.clientY; } - /** - * This is the number of clicks that occurs in 200ms/click of each other. - */ + /** This is the number of clicks that occurs in 200ms/click of each other. */ public detail: number; - /** - * The movement in this pointer relative to the last `mousemove` event. - */ + /** The movement in this pointer relative to the last `mousemove` event. */ public movement: Point = new Point(); /** @readonly */ @@ -84,9 +75,7 @@ export class FederatedMouseEvent extends FederatedEvent< /** @readonly */ get offsetY(): number { return this.offset.y; } - /** - * The pointer coordinates in world space. - */ + /** The pointer coordinates in world space. */ public global: Point = new Point(); /** @readonly */ @@ -103,21 +92,18 @@ export class FederatedMouseEvent extends FederatedEvent< /** * The pointer coordinates in the renderer's screen. Alias for {@code screen.x}. - * * @readonly */ get screenX(): number { return this.screen.x; } /** * The pointer coordinates in the renderer's screen. Alias for {@code screen.y}. - * * @readonly */ get screenY(): number { return this.screen.y; } /** * Whether the modifier key was pressed when this event natively occurred. - * * @param key - The modifier key. */ getModifierState(key: string): boolean @@ -127,8 +113,22 @@ export class FederatedMouseEvent extends FederatedEvent< /** * Not supported. - * - * @deprecated + * @param _typeArg + * @param _canBubbleArg + * @param _cancelableArg + * @param _viewArg + * @param _detailArg + * @param _screenXArg + * @param _screenYArg + * @param _clientXArg + * @param _clientYArg + * @param _ctrlKeyArg + * @param _altKeyArg + * @param _shiftKeyArg + * @param _metaKeyArg + * @param _buttonArg + * @param _relatedTargetArg + * @deprecated since 7.0.0 */ // eslint-disable-next-line max-params initMouseEvent( diff --git a/packages/events/src/FederatedPointerEvent.ts b/packages/events/src/FederatedPointerEvent.ts index 5f262350084..030baae2047 100644 --- a/packages/events/src/FederatedPointerEvent.ts +++ b/packages/events/src/FederatedPointerEvent.ts @@ -2,14 +2,12 @@ import { FederatedMouseEvent } from './FederatedMouseEvent'; /** * A {@link PIXI.FederatedEvent} for pointer events. - * * @memberof PIXI */ export class FederatedPointerEvent extends FederatedMouseEvent implements PointerEvent { /** * The unique identifier of the pointer. - * * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerId} */ public pointerId: number; @@ -17,7 +15,6 @@ export class FederatedPointerEvent extends FederatedMouseEvent implements Pointe /** * The width of the pointer's contact along the x-axis, measured in CSS pixels. * radiusX of TouchEvents will be represented by this value. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width */ public width = 0; @@ -25,21 +22,18 @@ export class FederatedPointerEvent extends FederatedMouseEvent implements Pointe /** * The height of the pointer's contact along the y-axis, measured in CSS pixels. * radiusY of TouchEvents will be represented by this value. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height */ public height = 0; /** * Indicates whether or not the pointer device that created the event is the primary pointer. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary */ public isPrimary = false; /** * The type of pointer that triggered the event. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType */ public pointerType: string; @@ -48,42 +42,35 @@ export class FederatedPointerEvent extends FederatedMouseEvent implements Pointe * Pressure applied by the pointing device during the event. *s * A Touch's force property will be represented by this value. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure */ public pressure: number; /** * Barrel pressure on a stylus pointer. - * * @see https://w3c.github.io/pointerevents/#pointerevent-interface */ public tangentialPressure: number; /** * The angle, in degrees, between the pointer device and the screen. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltX */ public tiltX: number; /** * The angle, in degrees, between the pointer device and the screen. - * * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltY */ public tiltY: number; /** * Twist of a stylus pointer. - * * @see https://w3c.github.io/pointerevents/#pointerevent-interface */ public twist: number; - /** - * This is the number of clicks that occurs in 200ms/click of each other. - */ + /** This is the number of clicks that occurs in 200ms/click of each other. */ public detail: number; // Only included for completeness for now diff --git a/packages/events/src/FederatedWheelEvent.ts b/packages/events/src/FederatedWheelEvent.ts index 89b5e6d5f5d..02965487d04 100644 --- a/packages/events/src/FederatedWheelEvent.ts +++ b/packages/events/src/FederatedWheelEvent.ts @@ -2,7 +2,6 @@ import { FederatedMouseEvent } from './FederatedMouseEvent'; /** * A {@link PIXI.FederatedEvent} for wheel events. - * * @memberof PIXI */ export class FederatedWheelEvent extends FederatedMouseEvent implements WheelEvent diff --git a/packages/events/test/EventBoundary.tests.ts b/packages/events/test/EventBoundary.tests.ts index 6e5c521e77f..e660c8acd62 100644 --- a/packages/events/test/EventBoundary.tests.ts +++ b/packages/events/test/EventBoundary.tests.ts @@ -1,12 +1,10 @@ import { Container } from '@pixi/display'; import { FederatedPointerEvent, EventBoundary } from '@pixi/events'; import { Graphics } from '@pixi/graphics'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('EventBoundary', function () +describe('EventBoundary', () => { - it('should fire capture, bubble events on the correct target', function () + it('should fire capture, bubble events on the correct target', () => { const stage = new Container(); const boundary = new EventBoundary(stage); @@ -19,9 +17,9 @@ describe('EventBoundary', function () new Graphics().drawRect(150, 0, 100, 100) ); const event = new FederatedPointerEvent(boundary); - const eventSpy = sinon.spy(); - const captureSpy = sinon.spy(); - const stageSpy = sinon.spy(); + const eventSpy = jest.fn(); + const captureSpy = jest.fn(); + const stageSpy = jest.fn(); target.interactive = true; container.interactive = true; @@ -34,8 +32,8 @@ describe('EventBoundary', function () target.addEventListener('click', { handleEvent(e) { - expect(this).to.not.be.undefined; - expect(e.eventPhase).to.equal(e.AT_TARGET); + expect(this).toBeDefined(); + expect(e.eventPhase).toEqual(e.AT_TARGET); eventSpy(); } @@ -44,13 +42,13 @@ describe('EventBoundary', function () stage.addEventListener('click', stageSpy); boundary.dispatchEvent(event); - expect(eventSpy).to.have.been.calledTwice; - expect(captureSpy).to.have.been.calledOnce; - expect(captureSpy).to.have.been.calledBefore(eventSpy); - expect(stageSpy).to.have.been.calledOnce; + expect(eventSpy).toBeCalledTimes(2); + expect(captureSpy).toHaveBeenCalledOnce(); + expect(captureSpy).toHaveBeenCalledBefore(eventSpy); + expect(stageSpy).toHaveBeenCalledOnce(); }); - it('should set hit-test target to most specific ancestor if hit object is not interactive', function () + it('should set hit-test target to most specific ancestor if hit object is not interactive', () => { const stage = new Container(); const boundary = new EventBoundary(stage); @@ -62,21 +60,22 @@ describe('EventBoundary', function () const hitTestTarget = boundary.hitTest(50, 50); - expect(hitTestTarget).to.equal(container); + expect(hitTestTarget).toEqual(container); }); - it('should fire pointerupoutside only on relevant & still mounted targets', function () + it('should fire pointerupoutside only on relevant & still mounted targets', () => { const stage = new Container(); const boundary = new EventBoundary(stage); const container = stage.addChild(new Container()); const pressed = container.addChild(new Graphics().beginFill(0).drawRect(0, 0, 100, 100)); - const outside = stage.addChild(new Graphics().beginFill(0).drawRect(100, 0, 100, 100)); - const eventSpy = sinon.spy(); - const containerSpy = sinon.spy(); - const stageSpy = sinon.spy(); - const stageOutsideSpy = sinon.spy(); + stage.addChild(new Graphics().beginFill(0).drawRect(100, 0, 100, 100)); + + const eventSpy = jest.fn(); + const containerSpy = jest.fn(); + const stageSpy = jest.fn(); + const stageOutsideSpy = jest.fn(); stage.interactive = true; container.interactive = true; @@ -101,24 +100,24 @@ describe('EventBoundary', function () off.global.set(150, 50); boundary.mapEvent(on); - expect(boundary.trackingData(1).pressTargetsByButton[1][2]).to.equal(pressed); + expect(boundary['trackingData'](1).pressTargetsByButton[1][2]).toEqual(pressed); pressed.destroy(); boundary.mapEvent(off); // "pressed" unmounted so it shouldn't get a pointerupoutside - expect(eventSpy).to.not.have.been.called; + expect(eventSpy).not.toBeCalled(); // "container" still mounted so it should get pointerupoutside - expect(containerSpy).to.have.been.calledOnce; + expect(containerSpy).toHaveBeenCalledOnce(); // "stage" still ancestor of the hit "outside" on pointerup, so it get pointerup instead - expect(stageOutsideSpy).to.not.have.been.called; + expect(stageOutsideSpy).not.toBeCalled(); // not a "pointerupoutside" - expect(stageSpy).to.have.been.calledOnce; + expect(stageSpy).toHaveBeenCalledOnce(); }); - it('should fire pointerout on the most specific mounted ancestor of pointerover target', function () + it('should fire pointerout on the most specific mounted ancestor of pointerover target', () => { const stage = new Container(); const boundary = new EventBoundary(stage); @@ -126,22 +125,22 @@ describe('EventBoundary', function () const over = container.addChild(new Graphics().beginFill(0).drawRect(0, 0, 100, 100)); const to = stage.addChild(new Graphics().beginFill(0).drawRect(100, 0, 100, 100)); - const orgOverSpy = sinon.spy(); - const orgContainerOverSpy = sinon.spy(); - const outSpy = sinon.spy(); - const containerOutSpy = sinon.spy(); - const toOverSpy = sinon.spy(); + const orgOverSpy = jest.fn(); + const orgContainerOverSpy = jest.fn(); + const outSpy = jest.fn(); + const containerOutSpy = jest.fn(); + const toOverSpy = jest.fn(); over.addEventListener('pointerover', orgOverSpy); - container.addEventListener('pointerover', function (e) + container.addEventListener('pointerover', (e) => { - expect(e.target).to.equal(over); + expect(e.target).toEqual(over); orgContainerOverSpy(); }); over.addEventListener('pointerout', outSpy); - container.addEventListener('pointerout', function (e) + container.addEventListener('pointerout', (e) => { - expect(e.target).to.equal(container); + expect(e.target).toEqual(container); containerOutSpy(); }); to.addEventListener('pointerover', toOverSpy); @@ -163,14 +162,14 @@ describe('EventBoundary', function () boundary.mapEvent(on); - expect(orgOverSpy).to.have.been.calledOnce; - expect(orgContainerOverSpy).to.have.been.calledOnce; + expect(orgOverSpy).toHaveBeenCalledOnce(); + expect(orgContainerOverSpy).toHaveBeenCalledOnce(); over.destroy(); boundary.mapEvent(off); - expect(outSpy).to.not.have.been.called; - expect(containerOutSpy).to.have.been.calledOnce; - expect(toOverSpy).to.have.been.calledOnce; + expect(outSpy).not.toBeCalled(); + expect(containerOutSpy).toHaveBeenCalledOnce(); + expect(toOverSpy).toHaveBeenCalledOnce(); }); }); diff --git a/packages/events/test/EventSystem.tests.ts b/packages/events/test/EventSystem.tests.ts index 18b71bf7158..fda55ca2572 100644 --- a/packages/events/test/EventSystem.tests.ts +++ b/packages/events/test/EventSystem.tests.ts @@ -1,22 +1,21 @@ import { Renderer } from '@pixi/core'; import { Container } from '@pixi/display'; -import { EventSystem } from '@pixi/events'; import { Graphics } from '@pixi/graphics'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import '@pixi/events'; -function createRenderer(view, supportsPointerEvents) +function createRenderer(view?: HTMLCanvasElement, supportsPointerEvents?: boolean) { - const renderer = Renderer.create({ + // TODO: event emitter types do not appear in tests + interface EERenderer extends Renderer + { + events: any + } + + const renderer = new Renderer({ width: 100, height: 100, view, - }); - - if (!renderer.events) - { - renderer.addSystem(EventSystem, 'events'); - } + }) as EERenderer; if (supportsPointerEvents === false) { @@ -44,7 +43,7 @@ function createScene() return [stage, graphics]; } -describe('EventSystem', function () +describe('EventSystem', () => { // Share WebGL context for performance const view = document.createElement('canvas'); @@ -83,7 +82,12 @@ describe('EventSystem', function () { type: 'touchstart' }, { type: 'touchendoutside', native: 'touchend' }, ] - ]; + ] as Array<{ + type: string; + clientX?: number; + clientY?: number; + native?: string; + }>; // Maps native event types to their listeners on EventSystem. const handlers = { @@ -108,7 +112,7 @@ describe('EventSystem', function () const isMouseEvent = events[0].type.startsWith('mouse'); const isTouchEvent = events[0].type.startsWith('touch'); - it(`should fire ${events[events.length - 1].type}`, function () + it(`should fire ${events[events.length - 1].type}`, () => { const renderer = createRenderer(view, isMouseEvent); const stage = new Container(); @@ -126,13 +130,13 @@ describe('EventSystem', function () clientX = clientX || 25; clientY = clientY || 25; - const eventSpy = sinon.spy(); - const handler = handlers[native || type]; + const eventSpy = jest.fn(); + const handler = handlers[(native || type) as keyof typeof handlers]; graphics.on(type, function testEvent(e) { - expect(e.nativeEvent.clientX).to.equal(clientX); - expect(e.nativeEvent.clientY).to.equal(clientY); + expect(e.nativeEvent.clientX).toEqual(clientX); + expect(e.nativeEvent.clientY).toEqual(clientY); eventSpy(); }); @@ -149,7 +153,6 @@ describe('EventSystem', function () new Touch({ identifier: 0, target: renderer.view, - isPrimary: true, clientX, clientY, }), @@ -163,12 +166,12 @@ describe('EventSystem', function () renderer.events[handler](event); - expect(eventSpy).to.have.been.calledOnce; + expect(eventSpy).toHaveBeenCalledOnce(); }); }); }); - it('should manage the CSS cursor', function () + it('should manage the CSS cursor', () => { const renderer = createRenderer(); const [stage, graphics] = createScene(); @@ -184,9 +187,9 @@ describe('EventSystem', function () }) ); - expect(renderer.view.style.cursor).to.equal('copy'); + expect(renderer.view.style.cursor).toEqual('copy'); - const eventSpy = sinon.spy(); + const eventSpy = jest.fn(); graphics.on('mousemove', eventSpy); renderer.events.onPointerMove( @@ -197,11 +200,11 @@ describe('EventSystem', function () }) ); - expect(eventSpy).to.not.have.been.called; - expect(renderer.view.style.cursor).to.equal('inherit'); + expect(eventSpy).not.toBeCalled(); + expect(renderer.view.style.cursor).toEqual('inherit'); }); - it('should dispatch synthetic over/out events on pointermove', function () + it('should dispatch synthetic over/out events on pointermove', () => { const renderer = createRenderer(); const [stage, graphics] = createScene(); @@ -214,45 +217,45 @@ describe('EventSystem', function () renderer.render(stage); second.interactive = true; - const primaryOverSpy = sinon.spy(); - const primaryOutSpy = sinon.spy(); - const primaryMoveSpy = sinon.spy(); + const primaryOverSpy = jest.fn(); + const primaryOutSpy = jest.fn(); + const primaryMoveSpy = jest.fn(); let callCount = 0; - graphics.on('pointerover', function () + graphics.on('pointerover', () => { - expect(callCount).to.equal(0); + expect(callCount).toEqual(0); primaryOverSpy(); ++callCount; }); - graphics.on('pointermove', function () + graphics.on('pointermove', () => { - expect(callCount).to.equal(1); + expect(callCount).toEqual(1); primaryMoveSpy(); ++callCount; }); - graphics.on('pointerout', function () + graphics.on('pointerout', () => { - expect(callCount).to.equal(2); + expect(callCount).toEqual(2); primaryOutSpy(); ++callCount; }); - const secondaryOverSpy = sinon.spy(); - const secondaryOutSpy = sinon.spy(); - const secondaryMoveSpy = sinon.spy(); + const secondaryOverSpy = jest.fn(); + const secondaryOutSpy = jest.fn(); + const secondaryMoveSpy = jest.fn(); - second.on('pointerover', function () + second.on('pointerover', () => { - expect(callCount).to.equal(3); + expect(callCount).toEqual(3); secondaryOverSpy(); ++callCount; }); second.on('pointerout', secondaryOutSpy); - second.on('pointermove', function () + second.on('pointermove', () => { - expect(callCount).to.equal(4); + expect(callCount).toEqual(4); secondaryMoveSpy(); ++callCount; }); @@ -260,29 +263,29 @@ describe('EventSystem', function () renderer.events.onPointerMove( new PointerEvent('pointermove', { clientX: 25, clientY: 25 }) ); - expect(primaryOverSpy).to.have.been.calledOnce; - expect(primaryMoveSpy).to.have.been.calledOnce; + expect(primaryOverSpy).toHaveBeenCalledOnce(); + expect(primaryMoveSpy).toHaveBeenCalledOnce(); renderer.events.onPointerMove( new PointerEvent('pointermove', { clientX: 125, clientY: 25 }) ); - expect(primaryOutSpy).to.have.been.calledOnce; - expect(secondaryOverSpy).to.have.been.calledOnce; - expect(secondaryMoveSpy).to.have.been.calledOnce; - expect(secondaryOutSpy).to.not.have.been.calledOnce; + expect(primaryOutSpy).toHaveBeenCalledOnce(); + expect(secondaryOverSpy).toHaveBeenCalledOnce(); + expect(secondaryMoveSpy).toHaveBeenCalledOnce(); + expect(secondaryOutSpy).not.toBeCalledTimes(1); }); - it('should dispatch click events', function () + it('should dispatch click events', () => { const renderer = createRenderer(); const [stage, graphics] = createScene(); - const eventSpy = sinon.spy(); + const eventSpy = jest.fn(); renderer.render(stage); - graphics.addEventListener('pointertap', function (e) + graphics.addEventListener('pointertap', (e) => { - expect(e.type).to.equal('click'); + expect(e.type).toEqual('click'); eventSpy(); }); @@ -298,22 +301,22 @@ describe('EventSystem', function () }); renderer.events.onPointerUp(e); - expect(eventSpy).to.have.been.calledOnce; + expect(eventSpy).toHaveBeenCalledOnce(); }); - it('should set the detail of click events to the click count', function (done) + it('should set the detail of click events to the click count', (done) => { const renderer = createRenderer(); const [stage, graphics] = createScene(); - const eventSpy = sinon.spy(); + const eventSpy = jest.fn(); let clickCount = 0; renderer.render(stage); - graphics.addEventListener('pointertap', function (e) + graphics.addEventListener('pointertap', (e) => { ++clickCount; - expect(e.detail).to.equal(clickCount); + expect((e as PointerEvent).detail).toEqual(clickCount); eventSpy(); }); @@ -332,19 +335,19 @@ describe('EventSystem', function () renderer.events.onPointerUp(e); } - expect(eventSpy).to.have.been.calledThrice; + expect(eventSpy).toBeCalledTimes(3); graphics.removeAllListeners(); - const newSpy = sinon.spy(); + const newSpy = jest.fn(); - graphics.addEventListener('pointertap', function (e) + graphics.addEventListener('pointertap', (e) => { - expect(e.detail).to.equal(1); + expect((e as PointerEvent).detail).toEqual(1); newSpy(); }); - setTimeout(function () + setTimeout(() => { renderer.events.onPointerDown( new PointerEvent('pointerdown', { clientX: 25, clientY: 25 }) @@ -358,7 +361,7 @@ describe('EventSystem', function () }); renderer.events.onPointerUp(e); - expect(newSpy).to.have.been.calledOnce; + expect(newSpy).toHaveBeenCalledOnce(); done(); }, 800); }); diff --git a/packages/canvas/canvas-extract/LICENSE b/packages/extensions/LICENSE similarity index 94% rename from packages/canvas/canvas-extract/LICENSE rename to packages/extensions/LICENSE index 148e3eb97d9..c871f16aa7e 100644 --- a/packages/canvas/canvas-extract/LICENSE +++ b/packages/extensions/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2018 Mathew Groves, Chad Engler +Copyright (c) 2022 Matt Karl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/extensions/README.md b/packages/extensions/README.md new file mode 100644 index 00000000000..ff52b9d50ec --- /dev/null +++ b/packages/extensions/README.md @@ -0,0 +1,15 @@ +# @pixi/extensions + +## Installation + +```bash +npm install @pixi/extensions +``` + +## Usage + +```js +import { extensions } from '@pixi/extensions'; + +extensions.add(MyCustomExtension); +``` \ No newline at end of file diff --git a/packages/extensions/package.json b/packages/extensions/package.json new file mode 100644 index 00000000000..5aaac4f04a9 --- /dev/null +++ b/packages/extensions/package.json @@ -0,0 +1,35 @@ +{ + "name": "@pixi/extensions", + "version": "7.0.0-alpha", + "main": "dist/cjs/extensions.js", + "module": "dist/esm/extensions.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/extensions.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/extensions.js" + } + } + }, + "description": "Installing and uninstalling extensions for PixiJS", + "author": "Matt Karl ", + "homepage": "http://pixijs.com/", + "bugs": "https://github.com/pixijs/pixi.js/issues", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/pixijs/pixi.js.git" + }, + "publishConfig": { + "access": "public" + }, + "files": [ + "dist", + "*.d.ts" + ] +} diff --git a/packages/extensions/src/index.ts b/packages/extensions/src/index.ts new file mode 100644 index 00000000000..d4b45b8e1ee --- /dev/null +++ b/packages/extensions/src/index.ts @@ -0,0 +1,257 @@ +/** + * Collection of valid extension types. + * @memberof PIXI + * @property {string} Application - Application plugins + * @property {string} RendererPlugin - Plugins for Renderer + * @property {string} CanvasRendererPlugin - Plugins for CanvasRenderer + * @property {string} Loader - Plugins to use with Loader + * @property {string} LoadParser - Parsers for Assets loader. + * @property {string} ResolveParser - Parsers for Assets resolvers. + * @property {string} CacheParser - Parsers for Assets cache. + */ +enum ExtensionType +// eslint-disable-next-line @typescript-eslint/indent +{ + Renderer = 'renderer', + Application = 'application', + RendererSystem = 'renderer-webgl-system', + RendererPlugin = 'renderer-webgl-plugin', + CanvasRendererSystem = 'renderer-canvas-system', + CanvasRendererPlugin = 'renderer-canvas-plugin', + LoadParser = 'load-parser', + ResolveParser = 'resolve-parser', + CacheParser = 'cache-parser', + DetectionParser = 'detection-parser', +} + +interface ExtensionMetadataDetails +{ + type: ExtensionType | ExtensionType[]; + name?: string; + priority?: number; +} + +type ExtensionMetadata = ExtensionType | ExtensionMetadataDetails; + +/** + * Format when registering an extension. Generally, the extension + * should have these values as `extension` static property, + * but you can override name or type by providing an object. + * @memberof PIXI + */ +interface ExtensionFormatLoose +{ + /** The extension type, can be multiple types */ + type: ExtensionType | ExtensionType[]; + /** Optional. Some plugins provide an API name/property, such as Renderer plugins */ + name?: string; + /** Optional, used for sorting the plugins in a particular order */ + priority?: number; + /** Reference to the plugin object/class */ + ref: any; +} + +/** + * Strict extension format that is used internally for registrations. + * @memberof PIXI + */ +interface ExtensionFormat extends ExtensionFormatLoose +{ + /** The extension type, always expressed as multiple, even if a single */ + type: ExtensionType[]; +} + +type ExtensionHandler = (extension: ExtensionFormat) => void; + +/** + * Convert input into extension format data. + * @ignore + */ +const normalizeExtension = (ext: ExtensionFormatLoose | any): ExtensionFormat => +{ + // Class/Object submission, use extension object + if (typeof ext === 'function' || (typeof ext === 'object' && ext.extension)) + { + // #if _DEBUG + if (!ext.extension) + { + throw new Error('Extension class must have an extension object'); + } + // #endif + const metadata: ExtensionMetadataDetails = (typeof ext.extension !== 'object') + ? { type: ext.extension } + : ext.extension; + + ext = { ...metadata, ref: ext }; + } + if (typeof ext === 'object') + { + ext = { ...ext }; + } + else + { + throw new Error('Invalid extension type'); + } + + if (typeof ext.type === 'string') + { + ext.type = [ext.type]; + } + + return ext; +}; + +/** + * Global registration of all PixiJS extensions. One-stop-shop for extensibility. + * @memberof PIXI + * @namespace extensions + */ +const extensions = { + + /** @ignore */ + _addHandlers: {} as Record, + + /** @ignore */ + _removeHandlers: {} as Record, + + /** @ignore */ + _queue: {} as Record, + + /** + * Remove extensions from PixiJS. + * @param extensions - Extensions to be removed. + * @returns {PIXI.extensions} For chaining. + */ + remove(...extensions: Array) + { + extensions.map(normalizeExtension).forEach((ext) => + { + ext.type.forEach((type) => this._removeHandlers[type]?.(ext)); + }); + + return this; + }, + + /** + * Register new extensions with PixiJS. + * @param extensions - The spread of extensions to add to PixiJS. + * @returns {PIXI.extensions} For chaining. + */ + add(...extensions: Array) + { + // Handle any extensions either passed as class w/ data or as data + extensions.map(normalizeExtension).forEach((ext) => + { + ext.type.forEach((type) => + { + const handlers = this._addHandlers; + const queue = this._queue; + + if (!handlers[type]) + { + queue[type] = queue[type] || []; + queue[type].push(ext); + } + else + { + handlers[type](ext); + } + }); + }); + + return this; + }, + + /** + * Internal method to handle extensions by name. + * @param type - The extension type. + * @param onAdd - Function for handling when extensions are added/registered passes {@link PIXI.ExtensionFormat}. + * @param onRemove - Function for handling when extensions are removed/unregistered passes {@link PIXI.ExtensionFormat}. + * @returns {PIXI.extensions} For chaining. + */ + handle(type: ExtensionType, onAdd: ExtensionHandler, onRemove: ExtensionHandler) + { + const addHandlers = this._addHandlers; + const removeHandlers = this._removeHandlers; + + // #if _DEBUG + if (addHandlers[type] || removeHandlers[type]) + { + throw new Error(`Extension type ${type} already has a handler`); + } + // #endif + + addHandlers[type] = onAdd; + removeHandlers[type] = onRemove; + + // Process the queue + const queue = this._queue; + + // Process any plugins that have been registered before the handler + if (queue[type]) + { + queue[type].forEach((ext) => onAdd(ext)); + delete queue[type]; + } + + return this; + }, + + /** + * Handle a type, but using a map by `name` property. + * @param type - Type of extension to handle. + * @param map - The object map of named extensions. + * @returns {PIXI.extensions} For chaining. + */ + handleByMap(type: ExtensionType, map: Record) + { + return this.handle(type, + (extension) => + { + map[extension.name] = extension.ref; + }, + (extension) => + { + delete map[extension.name]; + } + ); + }, + + /** + * Handle a type, but using a list of extensions. + * @param type - Type of extension to handle. + * @param list - The list of extensions. + * @returns {PIXI.extensions} For chaining. + */ + handleByList(type: ExtensionType, list: any[]) + { + return this.handle( + type, + (extension) => + { + list.push(extension.ref); + list.sort((a, b) => (b.priority ?? -1) - (a.priority ?? -1)); + }, + (extension) => + { + const index = list.indexOf(extension.ref); + + if (index !== -1) + { + list.splice(index, 1); + } + } + ); + }, +}; + +export { + extensions, + ExtensionType, +}; +export type { + ExtensionHandler, + ExtensionMetadata, + ExtensionFormatLoose, + ExtensionFormat, +}; diff --git a/packages/extensions/test/extensions.tests.ts b/packages/extensions/test/extensions.tests.ts new file mode 100644 index 00000000000..53e7fe37a4c --- /dev/null +++ b/packages/extensions/test/extensions.tests.ts @@ -0,0 +1,139 @@ +import type { ExtensionMetadata, ExtensionType } from '@pixi/extensions'; +import { extensions } from '@pixi/extensions'; + +const exampleType = 'test-extension' as ExtensionType; +const exampleType2 = 'test-extension2' as ExtensionType; + +const example = { + extension: { + type: exampleType, + name: 'test', + } as ExtensionMetadata, +}; + +const example2 = { + extension: exampleType as ExtensionMetadata, +}; + +describe('extensions', () => +{ + afterEach(() => + { + extensions['_addHandlers'][exampleType] = undefined; + extensions['_removeHandlers'][exampleType] = undefined; + extensions['_addHandlers'][exampleType2] = undefined; + extensions['_removeHandlers'][exampleType2] = undefined; + }); + + describe('handle', () => + { + it('should throw when extension type is handled twice', () => + { + extensions.handle(exampleType, () => null, () => null); + expect(() => + { + extensions.handle(exampleType, () => null, () => null); + }).toThrowError(`Extension type ${exampleType} already has a handler`); + }); + }); + + describe('handleByMap', () => + { + it('should successfully handle an extension by a map', () => + { + const map = {} as Record; + + extensions.handleByMap(exampleType, map); + extensions.add(example); + expect(map.test).toBe(example); + extensions.remove(example); + expect(map.test).toBeUndefined(); + }); + }); + + describe('handleByList', () => + { + it('should successfully handle an extension by a map', () => + { + const list: any[] = []; + + extensions.handleByList(exampleType, list); + extensions.add(example); + expect(list[0]).toBe(example); + extensions.remove(example); + expect(list[0]).toBeUndefined(); + }); + }); + + describe('add', () => + { + it('should register simple extension data', () => + { + const list: any[] = []; + + extensions.handleByList(exampleType, list); + extensions.add(example2); + expect(list.length).toBe(1); + expect(list[0]).toBe(example2); + extensions.remove(example2); + expect(list.length).toBe(0); + }); + + it('should support spread', () => + { + const list: any[] = []; + + extensions.handleByList(exampleType, list); + extensions.add(example2, example); + expect(list.length).toBe(2); + extensions.remove(example2, example); + expect(list.length).toBe(0); + }); + + it('should immedately register extension before handle', () => + { + const list: any[] = []; + + extensions.handleByList(exampleType, list); + extensions.add(example); + expect(list.length).toBe(1); + expect(list[0]).toBe(example); + extensions.remove(example); + expect(list.length).toBe(0); + }); + + it('should immedately register extension after handle', () => + { + const list: any[] = []; + + extensions.add(example); + extensions.handleByList(exampleType, list); + expect(list.length).toBe(1); + expect(list[0]).toBe(example); + extensions.remove(example); + expect(list.length).toBe(0); + }); + + it('should support multiple types', () => + { + const list: any[] = []; + const list2: any[] = []; + const example3 = { + extension: { + type: [exampleType, exampleType2] as ExtensionType[], + } as ExtensionMetadata, + }; + + extensions.handleByList(exampleType, list); + extensions.handleByList(exampleType2, list2); + extensions.add(example3); + expect(list.length).toBe(1); + expect(list2.length).toBe(1); + expect(list[0]).toBe(example3); + expect(list2[0]).toBe(example3); + extensions.remove(example3); + expect(list.length).toBe(0); + expect(list2.length).toBe(0); + }); + }); +}); diff --git a/packages/extract/README.md b/packages/extract/README.md index 96645f1cc26..0c5437f2b4c 100644 --- a/packages/extract/README.md +++ b/packages/extract/README.md @@ -9,8 +9,5 @@ npm install @pixi/extract ## Usage ```js -import { Extract } from '@pixi/canvas-extract'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('extract', Extract); +import '@pixi/canvas-extract'; ``` \ No newline at end of file diff --git a/packages/extract/global.d.ts b/packages/extract/global.d.ts new file mode 100644 index 00000000000..49710c604f6 --- /dev/null +++ b/packages/extract/global.d.ts @@ -0,0 +1,7 @@ +declare namespace GlobalMixins +{ + interface Renderer + { + readonly extract: import('@pixi/extract').Extract; + } +} diff --git a/packages/extract/package.json b/packages/extract/package.json index cfc5fce6d4d..e2c08212c5a 100644 --- a/packages/extract/package.json +++ b/packages/extract/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/extract", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/extract.js", - "module": "dist/esm/extract.js", - "bundle": "dist/browser/extract.js", + "module": "dist/esm/extract.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/extract.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/extract.js" + } + } + }, "description": "Extract raw graphics data from renderer", "author": "Mat Groves", "contributors": [ @@ -20,13 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/extract/src/Extract.ts b/packages/extract/src/Extract.ts index 7335bd42773..e2510f23348 100644 --- a/packages/extract/src/Extract.ts +++ b/packages/extract/src/Extract.ts @@ -1,8 +1,6 @@ -import { CanvasRenderTarget } from '@pixi/utils'; -import { Rectangle } from '@pixi/math'; -import { RenderTexture } from '@pixi/core'; +import { Rectangle, utils, extensions, ExtensionType, RenderTexture } from '@pixi/core'; -import type { Renderer, IRendererPlugin } from '@pixi/core'; +import type { Renderer, ISystem, ExtensionMetadata } from '@pixi/core'; import type { DisplayObject } from '@pixi/display'; const TEMP_RECT = new Rectangle(); @@ -14,7 +12,6 @@ const BYTES_PER_PIXEL = 4; * * Do not instantiate these plugins directly. It is available from the `renderer.plugins` property. * See {@link PIXI.CanvasRenderer#plugins} or {@link PIXI.Renderer#plugins}. - * * @example * // Create a new app (will auto-add extract plugin to renderer) * const app = new PIXI.Application(); @@ -27,11 +24,17 @@ const BYTES_PER_PIXEL = 4; * // Render the graphics as an HTMLImageElement * const image = app.renderer.plugins.extract.image(graphics); * document.body.appendChild(image); - * * @memberof PIXI */ -export class Extract implements IRendererPlugin + +export class Extract implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'extract', + type: ExtensionType.RendererSystem, + }; + private renderer: Renderer; /** @@ -44,14 +47,13 @@ export class Extract implements IRendererPlugin /** * Will return a HTML Image of the target - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer * @param format - Image format, e.g. "image/jpeg" or "image/webp". * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92. - * @return - HTML Image of the target + * @returns - HTML Image of the target */ - public image(target: DisplayObject|RenderTexture, format?: string, quality?: number): HTMLImageElement + public image(target: DisplayObject | RenderTexture, format?: string, quality?: number): HTMLImageElement { const image = new Image(); @@ -63,30 +65,28 @@ export class Extract implements IRendererPlugin /** * Will return a base64 encoded string of this target. It works by calling * `Extract.getCanvas` and then running toDataURL on that. - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer * @param format - Image format, e.g. "image/jpeg" or "image/webp". * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92. - * @return - A base64 encoded string of the texture. + * @returns - A base64 encoded string of the texture. */ - public base64(target: DisplayObject|RenderTexture, format?: string, quality?: number): string + public base64(target: DisplayObject | RenderTexture, format?: string, quality?: number): string { return this.canvas(target).toDataURL(format, quality); } /** * Creates a Canvas element, renders this target to it and then returns it. - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer - * @return - A Canvas element with the texture rendered on. + * @param frame - The frame the extraction is restricted to. + * @returns - A Canvas element with the texture rendered on. */ - public canvas(target: DisplayObject|RenderTexture): HTMLCanvasElement + public canvas(target: DisplayObject | RenderTexture, frame?: Rectangle): HTMLCanvasElement { const renderer = this.renderer; let resolution; - let frame; let flipY = false; let renderTexture; let generated = false; @@ -107,27 +107,29 @@ export class Extract implements IRendererPlugin if (renderTexture) { resolution = renderTexture.baseTexture.resolution; - frame = renderTexture.frame; + frame = frame ?? renderTexture.frame; flipY = false; renderer.renderTexture.bind(renderTexture); } else { - resolution = this.renderer.resolution; - - flipY = true; + resolution = renderer.resolution; - frame = TEMP_RECT; - frame.width = this.renderer.width; - frame.height = this.renderer.height; + if (!frame) + { + frame = TEMP_RECT; + frame.width = renderer.width; + frame.height = renderer.height; + } + flipY = true; renderer.renderTexture.bind(null); } - const width = Math.floor((frame.width * resolution) + 1e-4); - const height = Math.floor((frame.height * resolution) + 1e-4); + const width = Math.round(frame.width * resolution); + const height = Math.round(frame.height * resolution); - let canvasBuffer = new CanvasRenderTarget(width, height, 1); + let canvasBuffer = new utils.CanvasRenderTarget(width, height, 1); const webglPixels = new Uint8Array(BYTES_PER_PIXEL * width * height); @@ -135,8 +137,8 @@ export class Extract implements IRendererPlugin const gl = renderer.gl; gl.readPixels( - frame.x * resolution, - frame.y * resolution, + Math.round(frame.x * resolution), + Math.round(frame.y * resolution), width, height, gl.RGBA, @@ -154,7 +156,7 @@ export class Extract implements IRendererPlugin // pulling pixels if (flipY) { - const target = new CanvasRenderTarget(canvasBuffer.width, canvasBuffer.height, 1); + const target = new utils.CanvasRenderTarget(canvasBuffer.width, canvasBuffer.height, 1); target.context.scale(1, -1); @@ -177,16 +179,15 @@ export class Extract implements IRendererPlugin /** * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA * order, with integer values between 0 and 255 (included). - * * @param target - A displayObject or renderTexture * to convert. If left empty will use the main renderer - * @return - One-dimensional array containing the pixel data of the entire texture + * @param frame - The frame the extraction is restricted to. + * @returns - One-dimensional array containing the pixel data of the entire texture */ - public pixels(target?: DisplayObject|RenderTexture): Uint8Array + public pixels(target?: DisplayObject | RenderTexture, frame?: Rectangle): Uint8Array { const renderer = this.renderer; let resolution; - let frame; let renderTexture; let generated = false; @@ -206,24 +207,25 @@ export class Extract implements IRendererPlugin if (renderTexture) { resolution = renderTexture.baseTexture.resolution; - frame = renderTexture.frame; - - // bind the buffer + frame = frame ?? renderTexture.frame; renderer.renderTexture.bind(renderTexture); } else { resolution = renderer.resolution; - frame = TEMP_RECT; - frame.width = renderer.width; - frame.height = renderer.height; + if (!frame) + { + frame = TEMP_RECT; + frame.width = renderer.width; + frame.height = renderer.height; + } renderer.renderTexture.bind(null); } - const width = frame.width * resolution; - const height = frame.height * resolution; + const width = Math.round(frame.width * resolution); + const height = Math.round(frame.height * resolution); const webglPixels = new Uint8Array(BYTES_PER_PIXEL * width * height); @@ -231,8 +233,8 @@ export class Extract implements IRendererPlugin const gl = renderer.gl; gl.readPixels( - frame.x * resolution, - frame.y * resolution, + Math.round(frame.x * resolution), + Math.round(frame.y * resolution), width, height, gl.RGBA, @@ -258,7 +260,6 @@ export class Extract implements IRendererPlugin /** * Takes premultiplied pixel data and produces regular pixel data - * * @private * @param pixels - array of pixel data * @param out - output array @@ -286,3 +287,5 @@ export class Extract implements IRendererPlugin } } } + +extensions.add(Extract); diff --git a/packages/extract/test/Extract.tests.ts b/packages/extract/test/Extract.tests.ts index ab970b2a290..207e7701ac7 100644 --- a/packages/extract/test/Extract.tests.ts +++ b/packages/extract/test/Extract.tests.ts @@ -1,69 +1,64 @@ import { Sprite } from '@pixi/sprite'; -import { expect } from 'chai'; -import { skipHello } from '@pixi/utils'; -import { Texture, RenderTexture, BatchRenderer, Renderer } from '@pixi/core'; + +import { Rectangle, utils, Texture, RenderTexture, Renderer } from '@pixi/core'; import { Extract } from '@pixi/extract'; -skipHello(); +utils.skipHello(); -describe('Extract', function () +describe('Extract', () => { - before(function () - { - Renderer.registerPlugin('extract', Extract); - Renderer.registerPlugin('batch', BatchRenderer); - }); - - it('should access extract on renderer', function () + it('should access extract on renderer', () => { const renderer = new Renderer(); - expect(renderer.plugins.extract).to.be.an.instanceof(Extract); + expect(renderer.plugins.extract).toBeInstanceOf(Extract); + expect(renderer.extract).toBeInstanceOf(Extract); renderer.destroy(); }); - it('should extract an sprite', function () + it('should extract an sprite', () => { const renderer = new Renderer(); const sprite = new Sprite(Texture.WHITE); - const extract = renderer.plugins.extract as Extract; + const extract = renderer.extract; - expect(extract.canvas(sprite)).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64(sprite)).to.be.a('string'); - expect(extract.pixels(sprite)).to.be.instanceOf(Uint8Array); - expect(extract.image(sprite)).to.be.instanceOf(HTMLImageElement); + expect(extract.canvas(sprite)).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64(sprite)).toBeString(); + expect(extract.pixels(sprite)).toBeInstanceOf(Uint8Array); + expect(extract.image(sprite)).toBeInstanceOf(HTMLImageElement); renderer.destroy(); sprite.destroy(); }); - it('should extract with no arguments', function () + it('should extract with no arguments', () => { const renderer = new Renderer(); - const extract = renderer.plugins.extract as Extract; + const extract = renderer.extract; - expect(extract.canvas()).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64()).to.be.a('string'); - expect(extract.pixels()).to.be.instanceOf(Uint8Array); - expect(extract.image()).to.be.instanceOf(HTMLImageElement); + expect(extract.canvas(undefined)).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64(undefined)).toBeString(); + expect(extract.pixels()).toBeInstanceOf(Uint8Array); + expect(extract.image(undefined)).toBeInstanceOf(HTMLImageElement); renderer.destroy(); }); - it('should extract a render texture', function () + it('should extract a render texture', () => { const renderer = new Renderer(); - const extract = renderer.plugins.extract as Extract; + const extract = renderer.extract; const renderTexture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(Texture.WHITE); + const frame = new Rectangle(1, 2, 5, 6); renderer.render(sprite, { renderTexture }); - expect(extract.canvas(renderTexture)).to.be.an.instanceof(HTMLCanvasElement); - expect(extract.base64(renderTexture)).to.be.a('string'); - expect(extract.pixels(renderTexture)).to.be.instanceOf(Uint8Array); - expect(extract.image(renderTexture)).to.be.instanceOf(HTMLImageElement); + expect(extract.canvas(renderTexture)).toBeInstanceOf(HTMLCanvasElement); + expect(extract.base64(renderTexture)).toBeString(); + expect(extract.pixels(renderTexture, frame)).toBeInstanceOf(Uint8Array); + expect(extract.image(renderTexture)).toBeInstanceOf(HTMLImageElement); renderer.destroy(); renderTexture.destroy(); diff --git a/packages/canvas/canvas-sprite-tiling/LICENSE b/packages/filter-alpha/LICENSE similarity index 100% rename from packages/canvas/canvas-sprite-tiling/LICENSE rename to packages/filter-alpha/LICENSE diff --git a/packages/filters/filter-alpha/README.md b/packages/filter-alpha/README.md similarity index 100% rename from packages/filters/filter-alpha/README.md rename to packages/filter-alpha/README.md diff --git a/packages/filters/filter-alpha/package.json b/packages/filter-alpha/package.json similarity index 59% rename from packages/filters/filter-alpha/package.json rename to packages/filter-alpha/package.json index af84f6a4bc8..7074c5ac2cd 100644 --- a/packages/filters/filter-alpha/package.json +++ b/packages/filter-alpha/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-alpha", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-alpha.js", - "module": "dist/esm/filter-alpha.js", - "bundle": "dist/browser/filter-alpha.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-alpha.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-alpha.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-alpha.js" + } + } + }, "description": "Filter that applies alpha evenly across the entire display object and any opaque elements it contains", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-alpha/src/AlphaFilter.ts b/packages/filter-alpha/src/AlphaFilter.ts similarity index 99% rename from packages/filters/filter-alpha/src/AlphaFilter.ts rename to packages/filter-alpha/src/AlphaFilter.ts index b02e3485cf0..a8d124d396f 100644 --- a/packages/filters/filter-alpha/src/AlphaFilter.ts +++ b/packages/filter-alpha/src/AlphaFilter.ts @@ -13,7 +13,6 @@ import fragment from './alpha.frag'; * 1. Assign a blendMode to this filter, blend all elements inside display object with background. * * 2. To use clipping in display coordinates, assign a filterArea to the same container that has this filter. - * * @memberof PIXI.filters */ export class AlphaFilter extends Filter @@ -30,7 +29,6 @@ export class AlphaFilter extends Filter /** * Coefficient for alpha multiplication - * * @default 1 */ get alpha(): number diff --git a/packages/filters/filter-alpha/src/alpha.frag b/packages/filter-alpha/src/alpha.frag similarity index 100% rename from packages/filters/filter-alpha/src/alpha.frag rename to packages/filter-alpha/src/alpha.frag diff --git a/packages/filters/filter-alpha/src/index.ts b/packages/filter-alpha/src/index.ts similarity index 100% rename from packages/filters/filter-alpha/src/index.ts rename to packages/filter-alpha/src/index.ts diff --git a/packages/filter-alpha/test/AlphaFilter.tests.ts b/packages/filter-alpha/test/AlphaFilter.tests.ts new file mode 100644 index 00000000000..31c40735332 --- /dev/null +++ b/packages/filter-alpha/test/AlphaFilter.tests.ts @@ -0,0 +1,25 @@ +import { AlphaFilter } from '@pixi/filter-alpha'; + +describe('AlphaFilter', () => +{ + it('should construct filter', () => + { + const filter = new AlphaFilter(); + + expect(filter).toBeInstanceOf(AlphaFilter); + expect(filter.alpha).toEqual(1); + + filter.destroy(); + }); + + it('should allow alpha to be set', () => + { + const filter = new AlphaFilter(); + + filter.alpha = 0.5; + + expect(filter.alpha).toEqual(0.5); + + filter.destroy(); + }); +}); diff --git a/packages/canvas/canvas-renderer/LICENSE b/packages/filter-blur/LICENSE similarity index 100% rename from packages/canvas/canvas-renderer/LICENSE rename to packages/filter-blur/LICENSE diff --git a/packages/filters/filter-blur/README.md b/packages/filter-blur/README.md similarity index 100% rename from packages/filters/filter-blur/README.md rename to packages/filter-blur/README.md diff --git a/packages/filters/filter-blur/package.json b/packages/filter-blur/package.json similarity index 56% rename from packages/filters/filter-blur/package.json rename to packages/filter-blur/package.json index 9a5bb6d4d20..39360c61b1f 100644 --- a/packages/filters/filter-blur/package.json +++ b/packages/filter-blur/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-blur", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-blur.js", - "module": "dist/esm/filter-blur.js", - "bundle": "dist/browser/filter-blur.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-blur.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-blur.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-blur.js" + } + } + }, "description": "Filter that blurs the display object", "author": "Mat Groves", "contributors": [ @@ -21,12 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/settings": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-blur/src/BlurFilter.ts b/packages/filter-blur/src/BlurFilter.ts similarity index 93% rename from packages/filters/filter-blur/src/BlurFilter.ts rename to packages/filter-blur/src/BlurFilter.ts index 889f303144e..d5b08b2618a 100644 --- a/packages/filters/filter-blur/src/BlurFilter.ts +++ b/packages/filter-blur/src/BlurFilter.ts @@ -1,16 +1,12 @@ -import { Filter } from '@pixi/core'; -import { settings } from '@pixi/settings'; +import { Filter, settings, CLEAR_MODES } from '@pixi/core'; import { BlurFilterPass } from './BlurFilterPass'; -import { CLEAR_MODES } from '@pixi/constants'; -import type { FilterSystem, RenderTexture } from '@pixi/core'; -import type { BLEND_MODES } from '@pixi/constants'; +import type { BLEND_MODES, FilterSystem, RenderTexture } from '@pixi/core'; /** * The BlurFilter applies a Gaussian blur to an object. * * The strength of the blur can be set for the x-axis and y-axis separately. - * * @memberof PIXI.filters */ export class BlurFilter extends Filter @@ -42,7 +38,6 @@ export class BlurFilter extends Filter /** * Applies the filter. - * * @param filterManager - The manager. * @param input - The input target. * @param output - The output target. @@ -86,7 +81,6 @@ export class BlurFilter extends Filter /** * Sets the strength of both the blurX and blurY properties simultaneously - * * @default 2 */ get blur(): number @@ -102,7 +96,6 @@ export class BlurFilter extends Filter /** * Sets the number of passes for blur. More passes means higher quality bluring. - * * @default 1 */ get quality(): number @@ -117,7 +110,6 @@ export class BlurFilter extends Filter /** * Sets the strength of the blurX property - * * @default 2 */ get blurX(): number @@ -133,7 +125,6 @@ export class BlurFilter extends Filter /** * Sets the strength of the blurY property - * * @default 2 */ get blurY(): number @@ -149,7 +140,6 @@ export class BlurFilter extends Filter /** * Sets the blendmode of the filter - * * @default PIXI.BLEND_MODES.NORMAL */ get blendMode(): BLEND_MODES @@ -164,7 +154,6 @@ export class BlurFilter extends Filter /** * If set to true the edge of the target will be clamped - * * @default false */ get repeatEdgePixels(): boolean diff --git a/packages/filters/filter-blur/src/BlurFilterPass.ts b/packages/filter-blur/src/BlurFilterPass.ts similarity index 96% rename from packages/filters/filter-blur/src/BlurFilterPass.ts rename to packages/filter-blur/src/BlurFilterPass.ts index 2cb7982414d..eb5922b14be 100644 --- a/packages/filters/filter-blur/src/BlurFilterPass.ts +++ b/packages/filter-blur/src/BlurFilterPass.ts @@ -1,14 +1,11 @@ -import { Filter } from '@pixi/core'; -import { settings } from '@pixi/settings'; +import { Filter, settings, CLEAR_MODES } from '@pixi/core'; import { generateBlurVertSource } from './generateBlurVertSource'; import { generateBlurFragSource } from './generateBlurFragSource'; -import { CLEAR_MODES } from '@pixi/constants'; import type { FilterSystem, RenderTexture } from '@pixi/core'; /** * The BlurFilterPass applies a horizontal or vertical Gaussian blur to an object. - * * @memberof PIXI.filters */ export class BlurFilterPass extends Filter @@ -51,7 +48,6 @@ export class BlurFilterPass extends Filter /** * Applies the filter. - * * @param filterManager - The manager. * @param input - The input target. * @param output - The output target. @@ -125,7 +121,6 @@ export class BlurFilterPass extends Filter } /** * Sets the strength of both the blur. - * * @default 16 */ get blur(): number @@ -142,7 +137,6 @@ export class BlurFilterPass extends Filter /** * Sets the quality of the blur by modifying the number of passes. More passes means higher * quality bluring but the lower the performance. - * * @default 4 */ get quality(): number diff --git a/packages/filters/filter-blur/src/generateBlurFragSource.ts b/packages/filter-blur/src/generateBlurFragSource.ts similarity index 98% rename from packages/filters/filter-blur/src/generateBlurFragSource.ts rename to packages/filter-blur/src/generateBlurFragSource.ts index 090ad96e127..376d2c39567 100644 --- a/packages/filters/filter-blur/src/generateBlurFragSource.ts +++ b/packages/filter-blur/src/generateBlurFragSource.ts @@ -1,4 +1,5 @@ -interface IGAUSSIAN_VALUES { +interface IGAUSSIAN_VALUES +{ [x: number]: number[]; } const GAUSSIAN_VALUES: IGAUSSIAN_VALUES = { diff --git a/packages/filters/filter-blur/src/generateBlurVertSource.ts b/packages/filter-blur/src/generateBlurVertSource.ts similarity index 100% rename from packages/filters/filter-blur/src/generateBlurVertSource.ts rename to packages/filter-blur/src/generateBlurVertSource.ts diff --git a/packages/filters/filter-blur/src/getMaxBlurKernelSize.ts b/packages/filter-blur/src/getMaxBlurKernelSize.ts similarity index 100% rename from packages/filters/filter-blur/src/getMaxBlurKernelSize.ts rename to packages/filter-blur/src/getMaxBlurKernelSize.ts diff --git a/packages/filters/filter-blur/src/index.ts b/packages/filter-blur/src/index.ts similarity index 100% rename from packages/filters/filter-blur/src/index.ts rename to packages/filter-blur/src/index.ts diff --git a/packages/filter-blur/test/BlurFilter.tests.ts b/packages/filter-blur/test/BlurFilter.tests.ts new file mode 100644 index 00000000000..75e36c31e80 --- /dev/null +++ b/packages/filter-blur/test/BlurFilter.tests.ts @@ -0,0 +1,32 @@ +import { BlurFilter } from '@pixi/filter-blur'; + +describe('BlurFilter', () => +{ + it('should construct filter', () => + { + const filter = new BlurFilter(); + + expect(filter).toBeInstanceOf(BlurFilter); + expect(filter.blur).toEqual(8); + expect(filter.blurX).toEqual(8); + expect(filter.blurY).toEqual(8); + expect(filter.quality).toEqual(4); + + filter.destroy(); + }); + + it('should support repeatEdgePixels', () => + { + const filter = new BlurFilter(); + + expect(filter.repeatEdgePixels).toBe(false); + expect(filter.padding).toBeGreaterThan(0); + + filter.repeatEdgePixels = true; + + expect(filter.repeatEdgePixels).toBe(true); + expect(filter.padding).toEqual(0); + + filter.destroy(); + }); +}); diff --git a/packages/canvas/canvas-prepare/LICENSE b/packages/filter-color-matrix/LICENSE similarity index 100% rename from packages/canvas/canvas-prepare/LICENSE rename to packages/filter-color-matrix/LICENSE diff --git a/packages/filters/filter-color-matrix/README.md b/packages/filter-color-matrix/README.md similarity index 100% rename from packages/filters/filter-color-matrix/README.md rename to packages/filter-color-matrix/README.md diff --git a/packages/filters/filter-color-matrix/package.json b/packages/filter-color-matrix/package.json similarity index 57% rename from packages/filters/filter-color-matrix/package.json rename to packages/filter-color-matrix/package.json index bcfac4bdfe8..50c0014f92f 100644 --- a/packages/filters/filter-color-matrix/package.json +++ b/packages/filter-color-matrix/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-color-matrix", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-color-matrix.js", - "module": "dist/esm/filter-color-matrix.js", - "bundle": "dist/browser/filter-color-matrix.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-color-matrix.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-color-matrix.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-color-matrix.js" + } + } + }, "description": "Filter that lets you change RGBA via a 5x4 matrix transformation", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-color-matrix/src/ColorMatrixFilter.ts b/packages/filter-color-matrix/src/ColorMatrixFilter.ts similarity index 97% rename from packages/filters/filter-color-matrix/src/ColorMatrixFilter.ts rename to packages/filter-color-matrix/src/ColorMatrixFilter.ts index bd563d1f23a..8f6685f494a 100644 --- a/packages/filters/filter-color-matrix/src/ColorMatrixFilter.ts +++ b/packages/filter-color-matrix/src/ColorMatrixFilter.ts @@ -1,9 +1,9 @@ import { Filter, defaultFilterVertex } from '@pixi/core'; import fragment from './colorMatrix.frag'; -import type { ArrayFixed } from '@pixi/utils'; +import type { utils } from '@pixi/core'; -export type ColorMatrix = ArrayFixed; +export type ColorMatrix = utils.ArrayFixed; /** * The ColorMatrixFilter class lets you apply a 5x4 matrix transformation on the RGBA @@ -39,7 +39,6 @@ export class ColorMatrixFilter extends Filter /** * Transforms current matrix and set the new one - * * @param {number[]} matrix - 5x4 matrix * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -60,7 +59,6 @@ export class ColorMatrixFilter extends Filter /** * Multiplies two mat5's - * * @private * @param out - 5x4 matrix the receiving matrix * @param a - 5x4 matrix the first operand @@ -102,9 +100,8 @@ export class ColorMatrixFilter extends Filter /** * Create a Float32 Array and normalize the offset component to 0-1 - * * @param {number[]} matrix - 5x4 matrix - * @return {number[]} 5x4 matrix with all values between 0-1 + * @returns {number[]} 5x4 matrix with all values between 0-1 */ private _colorMatrix(matrix: ColorMatrix): ColorMatrix { @@ -121,7 +118,6 @@ export class ColorMatrixFilter extends Filter /** * Adjusts brightness - * * @param b - value of the brigthness (0-1, where 0 is black) * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -142,7 +138,6 @@ export class ColorMatrixFilter extends Filter * Sets each channel on the diagonal of the color matrix. * This can be used to achieve a tinting effect on Containers similar to the tint field of some * display objects like Sprite, Text, Graphics, and Mesh. - * * @param color - Color of the tint. This is a hex value. * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -165,7 +160,6 @@ export class ColorMatrixFilter extends Filter /** * Set the matrices in grey scales - * * @param scale - value of the grey (0-1, where 0 is black) * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -184,7 +178,6 @@ export class ColorMatrixFilter extends Filter /** * Set the black and white matrice. - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -202,7 +195,6 @@ export class ColorMatrixFilter extends Filter /** * Set the hue property of the color - * * @param rotation - in degrees * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -257,7 +249,6 @@ export class ColorMatrixFilter extends Filter * Set the contrast matrix, increase the separation between dark and bright * Increase contrast : shadows darker and highlights brighter * Decrease contrast : bring the shadows up and the highlights down - * * @param amount - value of the contrast (0-1) * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -280,7 +271,6 @@ export class ColorMatrixFilter extends Filter /** * Set the saturation matrix, increase the separation between colors * Increase saturation : increase contrast, brightness, and sharpness - * * @param amount - The saturation amount (0-1) * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -300,11 +290,7 @@ export class ColorMatrixFilter extends Filter this._loadMatrix(matrix, multiply); } - /** - * Desaturate image (remove color) - * - * Call the saturate function - */ + /** Desaturate image (remove color) Call the saturate function */ public desaturate(): void // eslint-disable-line no-unused-vars { this.saturate(-1); @@ -312,7 +298,6 @@ export class ColorMatrixFilter extends Filter /** * Negative image (inverse of classic rgb matrix) - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -330,7 +315,6 @@ export class ColorMatrixFilter extends Filter /** * Sepia image - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -348,7 +332,6 @@ export class ColorMatrixFilter extends Filter /** * Color motion picture process invented in 1916 (thanks Dominic Szablewski) - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -366,7 +349,6 @@ export class ColorMatrixFilter extends Filter /** * Polaroid filter - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -384,7 +366,6 @@ export class ColorMatrixFilter extends Filter /** * Filter who transforms : Red -> Blue and Blue -> Red - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -402,7 +383,6 @@ export class ColorMatrixFilter extends Filter /** * Color reversal film introduced by Eastman Kodak in 1935. (thanks Dominic Szablewski) - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -420,7 +400,6 @@ export class ColorMatrixFilter extends Filter /** * Brown delicious browni filter (thanks Dominic Szablewski) - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -438,7 +417,6 @@ export class ColorMatrixFilter extends Filter /** * Vintage filter (thanks Dominic Szablewski) - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -456,7 +434,6 @@ export class ColorMatrixFilter extends Filter /** * We don't know exactly what it does, kind of gradient map, but funny to play with! - * * @param desaturation - Tone values. * @param toned - Tone values. * @param lightColor - Tone values, example: `0xFFE580` @@ -491,7 +468,6 @@ export class ColorMatrixFilter extends Filter /** * Night effect - * * @param intensity - The intensity of the night effect. * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -514,7 +490,6 @@ export class ColorMatrixFilter extends Filter * Predator effect * * Erase the current matrix by setting a new indepent one - * * @param amount - how much the predator feels his future victim * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix @@ -551,7 +526,6 @@ export class ColorMatrixFilter extends Filter * LSD effect * * Multiply the current matrix - * * @param multiply - if true, current matrix and matrix are multiplied. If false, * just set the current matrix with @param matrix */ @@ -582,7 +556,6 @@ export class ColorMatrixFilter extends Filter /** * The matrix of the color matrix filter - * * @member {number[]} * @default [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0] */ @@ -602,7 +575,6 @@ export class ColorMatrixFilter extends Filter * When the value is 0, the original color is used without modification. * When the value is 1, the result color is used. * When in the range (0, 1) the color is interpolated between the original and result by this amount. - * * @default 1 */ get alpha(): number diff --git a/packages/filters/filter-color-matrix/src/colorMatrix.frag b/packages/filter-color-matrix/src/colorMatrix.frag similarity index 100% rename from packages/filters/filter-color-matrix/src/colorMatrix.frag rename to packages/filter-color-matrix/src/colorMatrix.frag diff --git a/packages/filters/filter-color-matrix/src/index.ts b/packages/filter-color-matrix/src/index.ts similarity index 100% rename from packages/filters/filter-color-matrix/src/index.ts rename to packages/filter-color-matrix/src/index.ts diff --git a/packages/filters/filter-color-matrix/test/ColorMatrixFilter.tests.ts b/packages/filter-color-matrix/test/ColorMatrixFilter.tests.ts similarity index 80% rename from packages/filters/filter-color-matrix/test/ColorMatrixFilter.tests.ts rename to packages/filter-color-matrix/test/ColorMatrixFilter.tests.ts index e6e2249c631..4f4ef9282d2 100644 --- a/packages/filters/filter-color-matrix/test/ColorMatrixFilter.tests.ts +++ b/packages/filter-color-matrix/test/ColorMatrixFilter.tests.ts @@ -1,26 +1,25 @@ import { ColorMatrixFilter } from '@pixi/filter-color-matrix'; -import { expect } from 'chai'; -describe('ColorMatrixFilter', function () +describe('ColorMatrixFilter', () => { - it('should construct filter', function () + it('should construct filter', () => { const filter = new ColorMatrixFilter(); - expect(filter).to.be.instanceOf(ColorMatrixFilter); - expect(filter.alpha).to.equal(1); + expect(filter).toBeInstanceOf(ColorMatrixFilter); + expect(filter.alpha).toEqual(1); filter.alpha = 0.5; - expect(filter.alpha).to.equal(0.5); - expect(filter.matrix).to.deep.eq(new Float32Array( + expect(filter.alpha).toEqual(0.5); + expect(filter.matrix).toEqual(new Float32Array( [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0] )); filter.destroy(); }); - it('should run all operations without multiply', function () + it('should run all operations without multiply', () => { const filter = new ColorMatrixFilter(); @@ -49,7 +48,7 @@ describe('ColorMatrixFilter', function () filter.destroy(); }); - it('should run all operations with multiply', function () + it('should run all operations with multiply', () => { const filter = new ColorMatrixFilter(); diff --git a/packages/canvas/canvas-particle-container/LICENSE b/packages/filter-displacement/LICENSE similarity index 100% rename from packages/canvas/canvas-particle-container/LICENSE rename to packages/filter-displacement/LICENSE diff --git a/packages/filters/filter-displacement/README.md b/packages/filter-displacement/README.md similarity index 100% rename from packages/filters/filter-displacement/README.md rename to packages/filter-displacement/README.md diff --git a/packages/filters/filter-displacement/package.json b/packages/filter-displacement/package.json similarity index 57% rename from packages/filters/filter-displacement/package.json rename to packages/filter-displacement/package.json index 480d027e73c..cbe22e52faa 100644 --- a/packages/filters/filter-displacement/package.json +++ b/packages/filter-displacement/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-displacement", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-displacement.js", - "module": "dist/esm/filter-displacement.js", - "bundle": "dist/browser/filter-displacement.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-displacement.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-displacement.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-displacement.js" + } + } + }, "description": "Filter that allows offsetting of pixel values to create warping effects", "author": "Mat Groves", "contributors": [ @@ -21,12 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-displacement/src/DisplacementFilter.ts b/packages/filter-displacement/src/DisplacementFilter.ts similarity index 93% rename from packages/filters/filter-displacement/src/DisplacementFilter.ts rename to packages/filter-displacement/src/DisplacementFilter.ts index ca50329024d..03e7e5446c6 100644 --- a/packages/filters/filter-displacement/src/DisplacementFilter.ts +++ b/packages/filter-displacement/src/DisplacementFilter.ts @@ -1,10 +1,8 @@ -import { Filter } from '@pixi/core'; -import { Matrix, Point } from '@pixi/math'; +import { Matrix, Point, Filter } from '@pixi/core'; import fragment from './displacement.frag'; import vertex from './displacement.vert'; -import type { CLEAR_MODES } from '@pixi/constants'; -import type { FilterSystem, RenderTexture, Texture, ISpriteMaskTarget } from '@pixi/core'; +import type { CLEAR_MODES, FilterSystem, RenderTexture, Texture, ISpriteMaskTarget } from '@pixi/core'; /** * The DisplacementFilter class uses the pixel values from the specified texture @@ -19,7 +17,6 @@ import type { FilterSystem, RenderTexture, Texture, ISpriteMaskTarget } from '@p * Instead, it's starting at the output and asking "which pixel from the original goes here". * For example, if a displacement map pixel has `red = 1` and the filter scale is `20`, * this filter will output the pixel approximately 20 pixels to the right of the original. - * * @memberof PIXI.filters */ export class DisplacementFilter extends Filter @@ -62,7 +59,6 @@ export class DisplacementFilter extends Filter /** * Applies the filter. - * * @param filterManager - The manager. * @param input - The input target. * @param output - The output target. diff --git a/packages/filters/filter-displacement/src/displacement.frag b/packages/filter-displacement/src/displacement.frag similarity index 100% rename from packages/filters/filter-displacement/src/displacement.frag rename to packages/filter-displacement/src/displacement.frag diff --git a/packages/filters/filter-displacement/src/displacement.vert b/packages/filter-displacement/src/displacement.vert similarity index 100% rename from packages/filters/filter-displacement/src/displacement.vert rename to packages/filter-displacement/src/displacement.vert diff --git a/packages/filters/filter-displacement/src/index.ts b/packages/filter-displacement/src/index.ts similarity index 100% rename from packages/filters/filter-displacement/src/index.ts rename to packages/filter-displacement/src/index.ts diff --git a/packages/canvas/canvas-mesh/LICENSE b/packages/filter-fxaa/LICENSE similarity index 100% rename from packages/canvas/canvas-mesh/LICENSE rename to packages/filter-fxaa/LICENSE diff --git a/packages/filters/filter-fxaa/README.md b/packages/filter-fxaa/README.md similarity index 100% rename from packages/filters/filter-fxaa/README.md rename to packages/filter-fxaa/README.md diff --git a/packages/filters/filter-fxaa/package.json b/packages/filter-fxaa/package.json similarity index 56% rename from packages/filters/filter-fxaa/package.json rename to packages/filter-fxaa/package.json index 282beb05b90..3808e925c93 100644 --- a/packages/filters/filter-fxaa/package.json +++ b/packages/filter-fxaa/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-fxaa", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-fxaa.js", - "module": "dist/esm/filter-fxaa.js", - "bundle": "dist/browser/filter-fxaa.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-fxaa.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-fxaa.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-fxaa.js" + } + } + }, "description": "Filter for fast approximate anti-aliasing", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-fxaa/src/FXAAFilter.ts b/packages/filter-fxaa/src/FXAAFilter.ts similarity index 98% rename from packages/filters/filter-fxaa/src/FXAAFilter.ts rename to packages/filter-fxaa/src/FXAAFilter.ts index d1b8caf7992..76831ffc70f 100644 --- a/packages/filters/filter-fxaa/src/FXAAFilter.ts +++ b/packages/filter-fxaa/src/FXAAFilter.ts @@ -5,9 +5,7 @@ import fragment from './fxaa.frag'; /** * Basic FXAA (Fast Approximate Anti-Aliasing) implementation based on the code on geeks3d.com * with the modification that the texture2DLod stuff was removed since it is unsupported by WebGL. - * * @see https://github.com/mitsuhiko/webgl-meincraft - * * @memberof PIXI.filters */ export class FXAAFilter extends Filter diff --git a/packages/filters/filter-fxaa/src/fxaa.frag b/packages/filter-fxaa/src/fxaa.frag similarity index 100% rename from packages/filters/filter-fxaa/src/fxaa.frag rename to packages/filter-fxaa/src/fxaa.frag diff --git a/packages/filters/filter-fxaa/src/fxaa.vert b/packages/filter-fxaa/src/fxaa.vert similarity index 100% rename from packages/filters/filter-fxaa/src/fxaa.vert rename to packages/filter-fxaa/src/fxaa.vert diff --git a/packages/filters/filter-fxaa/src/index.ts b/packages/filter-fxaa/src/index.ts similarity index 100% rename from packages/filters/filter-fxaa/src/index.ts rename to packages/filter-fxaa/src/index.ts diff --git a/packages/canvas/canvas-graphics/LICENSE b/packages/filter-noise/LICENSE similarity index 100% rename from packages/canvas/canvas-graphics/LICENSE rename to packages/filter-noise/LICENSE diff --git a/packages/filters/filter-noise/README.md b/packages/filter-noise/README.md similarity index 100% rename from packages/filters/filter-noise/README.md rename to packages/filter-noise/README.md diff --git a/packages/filters/filter-noise/package.json b/packages/filter-noise/package.json similarity index 57% rename from packages/filters/filter-noise/package.json rename to packages/filter-noise/package.json index 10552cf7a50..df695d1f32f 100644 --- a/packages/filters/filter-noise/package.json +++ b/packages/filter-noise/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/filter-noise", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/filter-noise.js", - "module": "dist/esm/filter-noise.js", - "bundle": "dist/browser/filter-noise.js", - "namespace": "PIXI.filters", + "module": "dist/esm/filter-noise.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/filter-noise.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/filter-noise.js" + } + } + }, "description": "Filter that applies noise to a display object", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/filters/filter-noise/src/NoiseFilter.ts b/packages/filter-noise/src/NoiseFilter.ts similarity index 99% rename from packages/filters/filter-noise/src/NoiseFilter.ts rename to packages/filter-noise/src/NoiseFilter.ts index 95000c5aa94..8c9fc59d349 100644 --- a/packages/filters/filter-noise/src/NoiseFilter.ts +++ b/packages/filter-noise/src/NoiseFilter.ts @@ -5,7 +5,6 @@ import fragment from './noise.frag'; * A Noise effect filter. * * original filter: https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/noise.js - * * @memberof PIXI.filters * @author Vico @vicocotea */ @@ -28,7 +27,6 @@ export class NoiseFilter extends Filter /** * The amount of noise to apply, this value should be in the range (0, 1]. - * * @default 0.5 */ get noise(): number diff --git a/packages/filters/filter-noise/src/index.ts b/packages/filter-noise/src/index.ts similarity index 100% rename from packages/filters/filter-noise/src/index.ts rename to packages/filter-noise/src/index.ts diff --git a/packages/filters/filter-noise/src/noise.frag b/packages/filter-noise/src/noise.frag similarity index 100% rename from packages/filters/filter-noise/src/noise.frag rename to packages/filter-noise/src/noise.frag diff --git a/packages/filters/filter-alpha/test/AlphaFilter.tests.ts b/packages/filters/filter-alpha/test/AlphaFilter.tests.ts deleted file mode 100644 index 87cddbbdcc4..00000000000 --- a/packages/filters/filter-alpha/test/AlphaFilter.tests.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { AlphaFilter } from '@pixi/filter-alpha'; -import { expect } from 'chai'; - -describe('AlphaFilter', function () -{ - it('should construct filter', function () - { - const filter = new AlphaFilter(); - - expect(filter).to.be.instanceOf(AlphaFilter); - expect(filter.alpha).to.equal(1); - - filter.destroy(); - }); - - it('should allow alpha to be set', function () - { - const filter = new AlphaFilter(); - - filter.alpha = 0.5; - - expect(filter.alpha).to.equal(0.5); - - filter.destroy(); - }); -}); diff --git a/packages/filters/filter-blur/test/BlurFilter.tests.ts b/packages/filters/filter-blur/test/BlurFilter.tests.ts deleted file mode 100644 index 41485517b74..00000000000 --- a/packages/filters/filter-blur/test/BlurFilter.tests.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BlurFilter } from '@pixi/filter-blur'; -import { expect } from 'chai'; - -describe('BlurFilter', function () -{ - it('should construct filter', function () - { - const filter = new BlurFilter(); - - expect(filter).to.be.instanceOf(BlurFilter); - expect(filter.blur).to.equal(8); - expect(filter.blurX).to.equal(8); - expect(filter.blurY).to.equal(8); - expect(filter.quality).to.equal(4); - - filter.destroy(); - }); - - it('should support repeatEdgePixels', function () - { - const filter = new BlurFilter(); - - expect(filter.repeatEdgePixels).to.be.false; - expect(filter.padding).to.be.greaterThan(0); - - filter.repeatEdgePixels = true; - - expect(filter.repeatEdgePixels).to.be.true; - expect(filter.padding).to.equal(0); - - filter.destroy(); - }); -}); diff --git a/packages/graphics-extras/package.json b/packages/graphics-extras/package.json index a5d1c17a57e..117c319fbd2 100644 --- a/packages/graphics-extras/package.json +++ b/packages/graphics-extras/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/graphics-extras", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/graphics-extras.js", - "module": "dist/esm/graphics-extras.js", - "bundle": "dist/browser/graphics-extras.js", - "bundleNoExports": true, + "module": "dist/esm/graphics-extras.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/graphics-extras.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/graphics-extras.js" + } + } + }, "description": "Additional Graphics functions for drawing special shapes.", "author": "Matt Karl ", "homepage": "http://pixijs.com/", @@ -18,12 +29,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/graphics" + ] } diff --git a/packages/graphics-extras/src/drawChamferRect.ts b/packages/graphics-extras/src/drawChamferRect.ts index ed8cbef6436..52db279d3ce 100644 --- a/packages/graphics-extras/src/drawChamferRect.ts +++ b/packages/graphics-extras/src/drawChamferRect.ts @@ -4,14 +4,14 @@ import type { Graphics } from '@pixi/graphics'; * Draw Rectangle with chamfer corners. These are angled corners. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawChamferRect + * @param this * @param {number} x - Upper left corner of rect * @param {number} y - Upper right corner of rect * @param {number} width - Width of rect * @param {number} height - Height of rect * @param {number} chamfer - non-zero real number, size of corner cutout - * @return {PIXI.Graphics} Returns self. + * @returns {PIXI.Graphics} Returns self. */ export function drawChamferRect(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/drawFilletRect.ts b/packages/graphics-extras/src/drawFilletRect.ts index e26647bd730..30012d4334f 100644 --- a/packages/graphics-extras/src/drawFilletRect.ts +++ b/packages/graphics-extras/src/drawFilletRect.ts @@ -5,14 +5,14 @@ import type { Graphics } from '@pixi/graphics'; * however it support negative numbers as well for the corner radius. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawFilletRect + * @param this * @param {number} x - Upper left corner of rect * @param {number} y - Upper right corner of rect * @param {number} width - Width of rect * @param {number} height - Height of rect * @param {number} fillet - accept negative or positive values - * @return {PIXI.Graphics} Returns self. + * @returns {PIXI.Graphics} Returns self. */ export function drawFilletRect(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/drawRegularPolygon.ts b/packages/graphics-extras/src/drawRegularPolygon.ts index 7767492b44f..5fad58ea3ef 100644 --- a/packages/graphics-extras/src/drawRegularPolygon.ts +++ b/packages/graphics-extras/src/drawRegularPolygon.ts @@ -4,14 +4,14 @@ import type { Graphics } from '@pixi/graphics'; * Draw a regular polygon where all sides are the same length. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawRegularPolygon + * @param this * @param {number} x - X position * @param {number} y - Y position * @param {number} radius - Polygon radius * @param {number} sides - Minimum value is 3 * @param {number} rotation - Starting rotation values in radians.. - * @return {PIXI.Graphics} + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ export function drawRegularPolygon(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/drawRoundedPolygon.ts b/packages/graphics-extras/src/drawRoundedPolygon.ts index 93a1bc4fe21..c06602a4ce0 100644 --- a/packages/graphics-extras/src/drawRoundedPolygon.ts +++ b/packages/graphics-extras/src/drawRoundedPolygon.ts @@ -4,15 +4,15 @@ import type { Graphics } from '@pixi/graphics'; * Draw a regular polygon with rounded corners. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawRoundedPolygon + * @param this * @param {number} x - X position * @param {number} y - Y position * @param {number} radius - Polygon radius * @param {number} sides - Minimum value is 3 * @param {number} corner - Corner size in pixels. * @param {number} rotation - Starting rotation values in radians.. - * @return {PIXI.Graphics} + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ export function drawRoundedPolygon(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/drawStar.ts b/packages/graphics-extras/src/drawStar.ts index 403f30046d8..265973139ea 100644 --- a/packages/graphics-extras/src/drawStar.ts +++ b/packages/graphics-extras/src/drawStar.ts @@ -1,9 +1,8 @@ import type { Graphics } from '@pixi/graphics'; -import { Polygon, PI_2 } from '@pixi/math'; +import { Polygon, PI_2 } from '@pixi/core'; /** * Draw a star shape with an arbitrary number of points. - * * @ignore */ class Star extends Polygon @@ -44,15 +43,15 @@ class Star extends Polygon * Draw a star shape with an arbitrary number of points. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawStar + * @param this * @param x - Center X position of the star * @param y - Center Y position of the star * @param points - The number of points of the star, must be > 1 * @param radius - The outer radius of the star * @param innerRadius - The inner radius between points, default half `radius` * @param rotation - The rotation of the star in radians, where 0 is vertical - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ export function drawStar(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/drawTorus.ts b/packages/graphics-extras/src/drawTorus.ts index eaa2d93b2ec..cd298f2e684 100644 --- a/packages/graphics-extras/src/drawTorus.ts +++ b/packages/graphics-extras/src/drawTorus.ts @@ -4,15 +4,15 @@ import type { Graphics } from '@pixi/graphics'; * Draw a torus shape, like a donut. Can be used for something like a circle loader. * * _Note: Only available with **@pixi/graphics-extras**._ - * * @method PIXI.Graphics#drawTorus + * @param this * @param {number} x - X position * @param {number} y - Y position * @param {number} innerRadius - Inner circle radius * @param {number} outerRadius - Outer circle radius * @param {number} [startArc=0] - Where to begin sweep, in radians, 0.0 = to the right * @param {number} [endArc=Math.PI*2] - Where to end sweep, in radians - * @return {PIXI.Graphics} + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ export function drawTorus(this: Graphics, x: number, diff --git a/packages/graphics-extras/src/index.ts b/packages/graphics-extras/src/index.ts index 795213c066a..808613cf89c 100644 --- a/packages/graphics-extras/src/index.ts +++ b/packages/graphics-extras/src/index.ts @@ -6,7 +6,8 @@ import { drawRegularPolygon } from './drawRegularPolygon'; import { drawRoundedPolygon } from './drawRoundedPolygon'; import { drawStar } from './drawStar'; -export interface IGraphicsExtras { +export interface IGraphicsExtras +{ drawTorus: typeof drawTorus; drawChamferRect: typeof drawChamferRect; drawFilletRect: typeof drawFilletRect; diff --git a/packages/graphics-extras/test/Graphics.tests.ts b/packages/graphics-extras/test/Graphics.tests.ts index 1c25189d6a1..7f3591c7eac 100644 --- a/packages/graphics-extras/test/Graphics.tests.ts +++ b/packages/graphics-extras/test/Graphics.tests.ts @@ -1,40 +1,40 @@ import { Graphics } from '@pixi/graphics'; -import { expect } from 'chai'; + import '@pixi/graphics-extras'; -describe('Graphics', function () +describe('Graphics', () => { - it('should have extras as mixins', function () + it('should have extras as mixins', () => { const g = new Graphics(); - expect(g.drawChamferRect).to.be.ok; - expect(g.drawFilletRect).to.be.ok; - expect(g.drawRegularPolygon).to.be.ok; - expect(g.drawRoundedPolygon).to.be.ok; - expect(g.drawStar).to.be.ok; - expect(g.drawTorus).to.be.ok; + expect(g.drawChamferRect).toBeTruthy(); + expect(g.drawFilletRect).toBeTruthy(); + expect(g.drawRegularPolygon).toBeTruthy(); + expect(g.drawRoundedPolygon).toBeTruthy(); + expect(g.drawStar).toBeTruthy(); + expect(g.drawTorus).toBeTruthy(); g.destroy(); }); - it('should call all commands with defaults', function () + it('should call all commands with defaults', () => { const g = new Graphics(); - expect(g.drawChamferRect(0, 0, 100, 100, 5)).equals(g); - expect(g.drawChamferRect(0, 0, 100, 100, 0)).equals(g); - expect(g.drawFilletRect(0, 0, 100, 100, -5)).equals(g); - expect(g.drawFilletRect(0, 0, 100, 100, 5)).equals(g); - expect(g.drawFilletRect(0, 0, 100, 100, 0)).equals(g); - expect(g.drawRegularPolygon(0, 0, 100, 5, 0)).equals(g); - expect(g.drawRoundedPolygon(0, 0, 100, 5, 10, 0)).equals(g); - expect(g.drawRoundedPolygon(0, 0, 100, 5, 10)).equals(g); - expect(g.drawRoundedPolygon(0, 0, 100, 5, 0)).equals(g); - expect(g.drawStar(0, 0, 5, 100, 50, 0)).equals(g); - expect(g.drawTorus(0, 0, 50, 100)).equals(g); - expect(g.drawTorus(0, 0, 50, 100, 0, Math.PI * 2)).equals(g); - expect(g.drawTorus(0, 0, 50, 100, 0.2, Math.PI)).equals(g); + expect(g.drawChamferRect(0, 0, 100, 100, 5)).toEqual(g); + expect(g.drawChamferRect(0, 0, 100, 100, 0)).toEqual(g); + expect(g.drawFilletRect(0, 0, 100, 100, -5)).toEqual(g); + expect(g.drawFilletRect(0, 0, 100, 100, 5)).toEqual(g); + expect(g.drawFilletRect(0, 0, 100, 100, 0)).toEqual(g); + expect(g.drawRegularPolygon(0, 0, 100, 5, 0)).toEqual(g); + expect(g.drawRoundedPolygon(0, 0, 100, 5, 10, 0)).toEqual(g); + expect(g.drawRoundedPolygon(0, 0, 100, 5, 10)).toEqual(g); + expect(g.drawRoundedPolygon(0, 0, 100, 5, 0)).toEqual(g); + expect(g.drawStar(0, 0, 5, 100, 50, 0)).toEqual(g); + expect(g.drawTorus(0, 0, 50, 100)).toEqual(g); + expect(g.drawTorus(0, 0, 50, 100, 0, Math.PI * 2)).toEqual(g); + expect(g.drawTorus(0, 0, 50, 100, 0.2, Math.PI)).toEqual(g); g.destroy(); }); diff --git a/packages/graphics/package.json b/packages/graphics/package.json index 8d02d2c2861..ea96c277a4a 100644 --- a/packages/graphics/package.json +++ b/packages/graphics/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/graphics", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/graphics.js", - "module": "dist/esm/graphics.js", - "bundle": "dist/browser/graphics.js", + "module": "dist/esm/graphics.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/graphics.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/graphics.js" + } + } + }, "description": "Draw primitive shapes such as lines, circles and rectangles to the display", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/sprite" + ] } diff --git a/packages/graphics/src/Graphics.ts b/packages/graphics/src/Graphics.ts index 683ed2ffd57..f9cfe1efe53 100644 --- a/packages/graphics/src/Graphics.ts +++ b/packages/graphics/src/Graphics.ts @@ -8,25 +8,27 @@ import { RoundedRectangle, Matrix, SHAPES, -} from '@pixi/math'; + BLEND_MODES, + Texture, + UniformGroup, + State, + Shader, + utils +} from '@pixi/core'; -import { Texture, UniformGroup, State, Renderer, BatchDrawCall, Shader } from '@pixi/core'; import { BezierUtils, QuadraticUtils, ArcUtils } from './utils'; -import { hex2rgb } from '@pixi/utils'; import { GraphicsGeometry } from './GraphicsGeometry'; import { FillStyle } from './styles/FillStyle'; import { LineStyle } from './styles/LineStyle'; -import { BLEND_MODES } from '@pixi/constants'; import { Container } from '@pixi/display'; +import { LINE_JOIN, LINE_CAP } from './const'; -import type { IShape, IPointData } from '@pixi/math'; +import type { IShape, IPointData, Renderer, BatchDrawCall } from '@pixi/core'; import type { IDestroyOptions } from '@pixi/display'; -import { LINE_JOIN, LINE_CAP } from './const'; -/** - * Batch element computed from Graphics geometry - */ -export interface IGraphicsBatchElement { +/** Batch element computed from Graphics geometry */ +export interface IGraphicsBatchElement +{ vertexData: Float32Array; blendMode: BLEND_MODES; indices: Uint16Array | Uint32Array; @@ -38,14 +40,16 @@ export interface IGraphicsBatchElement { _texture: Texture; } -export interface IFillStyleOptions { +export interface IFillStyleOptions +{ color?: number; alpha?: number; texture?: Texture; matrix?: Matrix; } -export interface ILineStyleOptions extends IFillStyleOptions { +export interface ILineStyleOptions extends IFillStyleOptions +{ width?: number; alignment?: number; native?: boolean; @@ -77,20 +81,12 @@ export interface Graphics extends GlobalMixins.Graphics, Container {} * an optimization, by passing it into a new Geometry object's constructor. Because of this * ability, it's important to call `destroy()` on Geometry objects once you are done with them, to * properly dereference each GraphicsGeometry and prevent memory leaks. - * * @memberof PIXI */ export class Graphics extends Container { - /** - * New rendering behavior for rounded rectangles: circular arcs instead of quadratic bezier curves. - * In the next major release, we'll enable this by default. - */ - public static nextRoundedRectBehavior = false; - /** * Temporary point to use for containsPoint. - * * @private */ static _TEMP_POINT = new Point(); @@ -106,7 +102,6 @@ export class Graphics extends Container /** * Current path - * * @readonly */ public currentPath: Polygon = null; @@ -148,7 +143,6 @@ export class Graphics extends Container * Includes vertex positions, face indices, normals, colors, UVs, and * custom attributes within buffers, reducing the cost of passing all * this data to the GPU. Can be shared between multiple Mesh or Graphics objects. - * * @readonly */ public get geometry(): GraphicsGeometry @@ -172,7 +166,6 @@ export class Graphics extends Container * of the object in exchange for taking up texture memory. It is also useful if you need the graphics * object to be anti-aliased, because it will be rendered using canvas. This is not recommended if * you are constantly redrawing the graphics element. - * * @name cacheAsBitmap * @member {boolean} * @memberof PIXI.Graphics# @@ -189,8 +182,7 @@ export class Graphics extends Container /** * Creates a new Graphics object with the same values as this one. * Note that only the geometry of the object is cloned, not its transform (position,scale,etc) - * - * @return - A clone of the graphics object + * @returns - A clone of the graphics object */ public clone(): Graphics { @@ -205,7 +197,6 @@ export class Graphics extends Container * primitive in the GraphicsGeometry list is rendered sequentially, modes * such as `PIXI.BLEND_MODES.ADD` and `PIXI.BLEND_MODES.MULTIPLY` will * be applied per-primitive. - * * @default PIXI.BLEND_MODES.NORMAL */ public set blendMode(value: BLEND_MODES) @@ -221,7 +212,6 @@ export class Graphics extends Container /** * The tint applied to each graphic shape. This is a hex value. A value of * 0xFFFFFF will remove any tint effect. - * * @default 0xFFFFFF */ public get tint(): number @@ -236,7 +226,6 @@ export class Graphics extends Container /** * The current fill style. - * * @readonly */ public get fill(): FillStyle @@ -246,7 +235,6 @@ export class Graphics extends Container /** * The current line style. - * * @readonly */ public get line(): LineStyle @@ -257,21 +245,19 @@ export class Graphics extends Container /** * Specifies the line style used for subsequent calls to Graphics methods such as the lineTo() * method or the drawCircle() method. - * * @param [width=0] - width of the line to draw, will update the objects stored style * @param [color=0x0] - color of the line to draw, will update the objects stored style * @param [alpha=1] - alpha of the line to draw, will update the objects stored style * @param [alignment=0.5] - alignment of the line to draw, (0 = inner, 0.5 = middle, 1 = outer). * WebGL only. * @param [native=false] - If true the lines will be draw using LINES instead of TRIANGLE_STRIP - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public lineStyle(width: number, color?: number, alpha?: number, alignment?: number, native?: boolean): this; /** * Specifies the line style used for subsequent calls to Graphics methods such as the lineTo() * method or the drawCircle() method. - * * @param options - Line style options * @param {number} [options.width=0] - width of the line to draw, will update the objects stored style * @param {number} [options.color=0x0] - color of the line to draw, will update the objects stored style @@ -282,7 +268,7 @@ export class Graphics extends Container * @param {PIXI.LINE_CAP}[options.cap=PIXI.LINE_CAP.BUTT] - line cap style * @param {PIXI.LINE_JOIN}[options.join=PIXI.LINE_JOIN.MITER] - line join style * @param {number}[options.miterLimit=10] - miter limit ratio - * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ public lineStyle(options?: ILineStyleOptions): this; @@ -300,8 +286,7 @@ export class Graphics extends Container /** * Like line style but support texture for line fill. - * - * @param options - Collection of options for setting line style. + * @param [options] - Collection of options for setting line style. * @param {number} [options.width=0] - width of the line to draw, will update the objects stored style * @param {PIXI.Texture} [options.texture=PIXI.Texture.WHITE] - Texture to use * @param {number} [options.color=0x0] - color of the line to draw, will update the objects stored style. @@ -314,15 +299,15 @@ export class Graphics extends Container * @param {PIXI.LINE_CAP}[options.cap=PIXI.LINE_CAP.BUTT] - line cap style * @param {PIXI.LINE_JOIN}[options.join=PIXI.LINE_JOIN.MITER] - line join style * @param {number}[options.miterLimit=10] - miter limit ratio - * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ - public lineTextureStyle(options: ILineStyleOptions): this + public lineTextureStyle(options?: ILineStyleOptions): this { // Apply defaults options = Object.assign({ width: 0, texture: Texture.WHITE, - color: (options && options.texture) ? 0xFFFFFF : 0x0, + color: options?.texture ? 0xFFFFFF : 0x0, alpha: 1, matrix: null, alignment: 0.5, @@ -359,7 +344,6 @@ export class Graphics extends Container /** * Start a polygon object internally. - * * @protected */ protected startPoly(): void @@ -386,7 +370,6 @@ export class Graphics extends Container /** * Finish the polygon object. - * * @protected */ finishPoly(): void @@ -407,10 +390,9 @@ export class Graphics extends Container /** * Moves the current drawing position to x, y. - * * @param x - the X coordinate to move to * @param y - the Y coordinate to move to - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public moveTo(x: number, y: number): this { @@ -424,10 +406,9 @@ export class Graphics extends Container /** * Draws a line using the current line style from the current drawing position to (x, y); * The current drawing position is then set to (x, y). - * * @param x - the X coordinate to draw to * @param y - the Y coordinate to draw to - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public lineTo(x: number, y: number): this { @@ -449,7 +430,11 @@ export class Graphics extends Container return this; } - /** Initialize the curve */ + /** + * Initialize the curve + * @param x + * @param y + */ protected _initCurve(x = 0, y = 0): void { if (this.currentPath) @@ -468,12 +453,11 @@ export class Graphics extends Container /** * Calculate the points for a quadratic bezier curve and then draws it. * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c - * * @param cpX - Control point x * @param cpY - Control point y * @param toX - Destination point x * @param toY - Destination point y - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public quadraticCurveTo(cpX: number, cpY: number, toX: number, toY: number): this { @@ -493,14 +477,13 @@ export class Graphics extends Container /** * Calculate the points for a bezier curve and then draws it. - * * @param cpX - Control point x * @param cpY - Control point y * @param cpX2 - Second Control point x * @param cpY2 - Second Control point y * @param toX - Destination point x * @param toY - Destination point y - * @return This Graphics object. Good for chaining method calls + * @returns This Graphics object. Good for chaining method calls */ public bezierCurveTo(cpX: number, cpY: number, cpX2: number, cpY2: number, toX: number, toY: number): this { @@ -515,13 +498,12 @@ export class Graphics extends Container * The arcTo() method creates an arc/curve between two tangents on the canvas. * * "borrowed" from https://code.google.com/p/fxcanvas/ - thanks google! - * * @param x1 - The x-coordinate of the first tangent point of the arc * @param y1 - The y-coordinate of the first tangent point of the arc * @param x2 - The x-coordinate of the end of the arc * @param y2 - The y-coordinate of the end of the arc * @param radius - The radius of the arc - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): this { @@ -543,7 +525,6 @@ export class Graphics extends Container /** * The arc method creates an arc/curve (used to create circles, or parts of circles). - * * @param cx - The x-coordinate of the center of the circle * @param cy - The y-coordinate of the center of the circle * @param radius - The radius of the circle @@ -553,7 +534,7 @@ export class Graphics extends Container * @param anticlockwise - Specifies whether the drawing should be * counter-clockwise or clockwise. False is default, and indicates clockwise, while true * indicates counter-clockwise. - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public arc(cx: number, cy: number, radius: number, startAngle: number, endAngle: number, anticlockwise = false): this { @@ -617,10 +598,9 @@ export class Graphics extends Container /** * Specifies a simple one-color fill that subsequent calls to other Graphics methods * (such as lineTo() or drawCircle()) use when drawing. - * * @param color - the color of the fill * @param alpha - the alpha of the fill - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public beginFill(color = 0, alpha = 1): this { @@ -629,13 +609,12 @@ export class Graphics extends Container /** * Begin the texture fill - * * @param options - Object object. * @param {PIXI.Texture} [options.texture=PIXI.Texture.WHITE] - Texture to fill * @param {number} [options.color=0xffffff] - Background to fill behind texture * @param {number} [options.alpha=1] - Alpha of fill * @param {PIXI.Matrix} [options.matrix=null] - Transform matrix - * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + * @returns {PIXI.Graphics} This Graphics object. Good for chaining method calls */ beginTextureFill(options?: IFillStyleOptions): this { @@ -674,8 +653,7 @@ export class Graphics extends Container /** * Applies a fill to the lines and shapes that were added since the last call to the beginFill() method. - * - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public endFill(): this { @@ -688,12 +666,11 @@ export class Graphics extends Container /** * Draws a rectangle shape. - * * @param x - The X coord of the top-left of the rectangle * @param y - The Y coord of the top-left of the rectangle * @param width - The width of the rectangle * @param height - The height of the rectangle - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public drawRect(x: number, y: number, width: number, height: number): this { @@ -702,13 +679,12 @@ export class Graphics extends Container /** * Draw a rectangle shape with rounded/beveled corners. - * * @param x - The X coord of the top-left of the rectangle * @param y - The Y coord of the top-left of the rectangle * @param width - The width of the rectangle * @param height - The height of the rectangle * @param radius - Radius of the rectangle corners - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public drawRoundedRect(x: number, y: number, width: number, height: number, radius: number): this { @@ -717,11 +693,10 @@ export class Graphics extends Container /** * Draws a circle. - * * @param x - The X coordinate of the center of the circle * @param y - The Y coordinate of the center of the circle * @param radius - The radius of the circle - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public drawCircle(x: number, y: number, radius: number): this { @@ -730,30 +705,28 @@ export class Graphics extends Container /** * Draws an ellipse. - * * @param x - The X coordinate of the center of the ellipse * @param y - The Y coordinate of the center of the ellipse * @param width - The half width of the ellipse * @param height - The half height of the ellipse - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public drawEllipse(x: number, y: number, width: number, height: number): this { return this.drawShape(new Ellipse(x, y, width, height)); } - public drawPolygon(...path: Array | Array): this - public drawPolygon(path: Array | Array | Polygon): this + public drawPolygon(...path: Array | Array): this; + public drawPolygon(path: Array | Array | Polygon): this; /** * Draws a polygon using the given path. - * - * @param {number[]|PIXI.Point[]|PIXI.Polygon} path - The path data used to construct the polygon. - * @return - This Graphics object. Good for chaining method calls + * @param {number[]|PIXI.IPointData[]|PIXI.Polygon} path - The path data used to construct the polygon. + * @returns - This Graphics object. Good for chaining method calls */ public drawPolygon(...path: any[]): this { - let points: Array | Array; + let points: Array | Array; let closeStroke = true;// !!this._fillStyle; const poly = path[0] as Polygon; @@ -785,9 +758,8 @@ export class Graphics extends Container /** * Draw any shape. - * * @param {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} shape - Shape to draw - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public drawShape(shape: IShape): this { @@ -810,8 +782,7 @@ export class Graphics extends Container /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @return - This Graphics object. Good for chaining method calls + * @returns - This Graphics object. Good for chaining method calls */ public clear(): this { @@ -830,7 +801,6 @@ export class Graphics extends Container /** * True if graphics consists of one rectangle, and thus, can be drawn like a Sprite and * masked with gl.scissor. - * * @returns - True if only 1 rect. */ public isFastRect(): boolean @@ -846,7 +816,6 @@ export class Graphics extends Container /** * Renders the object using the WebGL renderer - * * @param renderer - The renderer */ protected _render(renderer: Renderer): void @@ -854,11 +823,10 @@ export class Graphics extends Container this.finishPoly(); const geometry = this._geometry; - const hasuint32 = renderer.context.supports.uint32Indices; // batch part.. // batch it! - geometry.updateBatches(hasuint32); + geometry.updateBatches(); if (geometry.batchable) { @@ -913,7 +881,7 @@ export class Graphics extends Container blendMode, indices, uvs, - _batchRGB: hex2rgb(color) as Array, + _batchRGB: utils.hex2rgb(color) as Array, _tintRGB: color, _texture: gI.style.texture, alpha: gI.style.alpha, @@ -925,7 +893,6 @@ export class Graphics extends Container /** * Renders the batches using the BathedRenderer plugin - * * @param renderer - The renderer */ protected _renderBatched(renderer: Renderer): void @@ -952,7 +919,6 @@ export class Graphics extends Container /** * Renders the graphics direct - * * @param renderer - The renderer */ protected _renderDirect(renderer: Renderer): void @@ -992,7 +958,11 @@ export class Graphics extends Container } } - /** Renders specific DrawCall */ + /** + * Renders specific DrawCall + * @param renderer + * @param drawCall + */ protected _renderDrawCallDirect(renderer: Renderer, drawCall: BatchDrawCall): void { const { texArray, type, size, start } = drawCall; @@ -1008,7 +978,6 @@ export class Graphics extends Container /** * Resolves shader for direct rendering - * * @param renderer - The renderer */ protected _resolveDirectShader(renderer: Renderer): Shader @@ -1024,7 +993,7 @@ export class Graphics extends Container // but may be more than one plugins for graphics if (!DEFAULT_SHADERS[pluginName]) { - const MAX_TEXTURES = renderer.plugins.batch.MAX_TEXTURES; + const { MAX_TEXTURES } = renderer.plugins[pluginName]; const sampleValues = new Int32Array(MAX_TEXTURES); for (let i = 0; i < MAX_TEXTURES; i++) @@ -1069,9 +1038,8 @@ export class Graphics extends Container /** * Tests if a point is inside this graphics object - * * @param point - the point to test - * @return - the result of the test + * @returns - the result of the test */ public containsPoint(point: IPointData): boolean { @@ -1087,7 +1055,7 @@ export class Graphics extends Container { this.batchTint = this.tint; - const tintRGB = hex2rgb(this.tint, temp); + const tintRGB = utils.hex2rgb(this.tint, temp); for (let i = 0; i < this.batches.length; i++) { @@ -1109,10 +1077,7 @@ export class Graphics extends Container } } - /** - * If there's a transform update or a change to the shape of the - * geometry, recalculate the vertices. - */ + /** If there's a transform update or a change to the shape of the geometry, recalculate the vertices. */ protected calculateVertices(): void { const wtID = this.transform._worldID; @@ -1149,8 +1114,7 @@ export class Graphics extends Container /** * Closes the current path. - * - * @return - Returns itself. + * @returns - Returns itself. */ public closePath(): this { @@ -1170,9 +1134,8 @@ export class Graphics extends Container /** * Apply a matrix to the positional data. - * * @param matrix - Matrix to use for transform current shape. - * @return - Returns itself. + * @returns - Returns itself. */ public setMatrix(matrix: Matrix): this { @@ -1187,8 +1150,7 @@ export class Graphics extends Container * Also weirdness ensues if holes overlap! * Ellipses, Circles, Rectangles and Rounded Rectangles cannot be holes or host for holes in CanvasRenderer, * please use `moveTo` `lineTo`, `quadraticCurveTo` if you rely on pixi-legacy bundle. - * - * @return - Returns itself. + * @returns - Returns itself. */ public beginHole(): this { @@ -1200,8 +1162,7 @@ export class Graphics extends Container /** * End adding holes to the last draw shape. - * - * @return - Returns itself. + * @returns - Returns itself. */ public endHole(): this { @@ -1213,7 +1174,6 @@ export class Graphics extends Container /** * Destroys the Graphics object. - * * @param options - Options parameter. A boolean will act as if all * options have been set to that value * @param {boolean} [options.children=false] - if set to true, all the children will have @@ -1223,7 +1183,7 @@ export class Graphics extends Container * @param {boolean} [options.baseTexture=false] - Only used for child Sprites if options.children is set to true * Should it destroy the base texture of the child sprite */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { this._geometry.refCount--; if (this._geometry.refCount === 0) diff --git a/packages/graphics/src/GraphicsData.ts b/packages/graphics/src/GraphicsData.ts index 03d282c6cfc..b422075d185 100644 --- a/packages/graphics/src/GraphicsData.ts +++ b/packages/graphics/src/GraphicsData.ts @@ -1,17 +1,15 @@ -import type { Matrix, SHAPES, IShape } from '@pixi/math'; +import type { Matrix, SHAPES, IShape } from '@pixi/core'; import type { FillStyle } from './styles/FillStyle'; import type { LineStyle } from './styles/LineStyle'; /** * A class to contain data useful for Graphics objects - * * @memberof PIXI */ export class GraphicsData { /** * The shape object to draw. - * * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ shape: IShape; @@ -52,8 +50,7 @@ export class GraphicsData /** * Creates a new GraphicsData object with the same values as this one. - * - * @return - Cloned GraphicsData object + * @returns - Cloned GraphicsData object */ public clone(): GraphicsData { diff --git a/packages/graphics/src/GraphicsGeometry.ts b/packages/graphics/src/GraphicsGeometry.ts index 92dafd8acbd..dca11cac685 100644 --- a/packages/graphics/src/GraphicsGeometry.ts +++ b/packages/graphics/src/GraphicsGeometry.ts @@ -12,16 +12,16 @@ import { BatchDrawCall, BatchTextureArray, BaseTexture, - Texture, + DRAW_MODES, + WRAP_MODES, + Point, + utils, } from '@pixi/core'; -import { DRAW_MODES, WRAP_MODES } from '@pixi/constants'; -import { SHAPES, Point, Matrix } from '@pixi/math'; import { GraphicsData } from './GraphicsData'; -import { premultiplyTint } from '@pixi/utils'; import { Bounds } from '@pixi/display'; -import type { Circle, Ellipse, Polygon, Rectangle, RoundedRectangle, IPointData } from '@pixi/math'; +import type { Texture, Circle, Ellipse, Polygon, Rectangle, RoundedRectangle, IPointData, Matrix } from '@pixi/core'; import type { FillStyle } from './styles/FillStyle'; import type { LineStyle } from './styles/LineStyle'; @@ -32,7 +32,6 @@ import type { LineStyle } from './styles/LineStyle'; type IShape = Circle | Ellipse | Polygon | Rectangle | RoundedRectangle; const tmpPoint = new Point(); -const tmpBounds = new Bounds(); /** * The Graphics class contains methods used to draw primitive shapes such as lines, circles and @@ -40,7 +39,6 @@ const tmpBounds = new Bounds(); * * GraphicsGeometry is designed to not be continually updating the geometry since it's expensive * to re-tesselate using **earcut**. Consider using {@link PIXI.Mesh} for this use-case, it's much faster. - * * @memberof PIXI */ export class GraphicsGeometry extends BatchGeometry @@ -48,13 +46,11 @@ export class GraphicsGeometry extends BatchGeometry /** * The maximum number of points to consider an object "batchable", * able to be batched by the renderer's batch system. -\ */ +\ + */ public static BATCHABLE_SIZE = 100; - /** - * Minimal distance between points that are considered different. - * Affects line tesselation. - */ + /** Minimal distance between points that are considered different. Affects line tesselation. */ public closePointEps = 1e-4; /** Padding to add to the bounds. */ @@ -81,14 +77,12 @@ export class GraphicsGeometry extends BatchGeometry /** * The collection of drawn shapes. - * * @member {PIXI.GraphicsData[]} */ graphicsData: Array = []; /** * List of current draw calls drived from the batches. - * * @member {PIXI.BatchDrawCall[]} */ drawCalls: Array = []; @@ -99,7 +93,6 @@ export class GraphicsGeometry extends BatchGeometry /** * Intermediate abstract format sent to batch system. * Can be converted to drawCalls or to batchable objects. - * * @member {PIXI.graphicsUtils.BatchPart[]} */ batches: Array = []; @@ -130,11 +123,12 @@ export class GraphicsGeometry extends BatchGeometry /** * Get the current bounds of the graphic geometry. - * * @readonly */ public get bounds(): Bounds { + this.updateBatches(); + if (this.boundsDirty !== this.dirty) { this.boundsDirty = this.dirty; @@ -144,10 +138,7 @@ export class GraphicsGeometry extends BatchGeometry return this._bounds; } - /** - * Call if you changed graphicsData manually. - * Empties all batch buffers. - */ + /** Call if you changed graphicsData manually. Empties all batch buffers. */ protected invalidate(): void { this.boundsDirty = -1; @@ -182,8 +173,7 @@ export class GraphicsGeometry extends BatchGeometry /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. - * - * @return - This GraphicsGeometry object. Good for chaining method calls + * @returns - This GraphicsGeometry object. Good for chaining method calls */ public clear(): GraphicsGeometry { @@ -199,12 +189,11 @@ export class GraphicsGeometry extends BatchGeometry /** * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * * @param {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} shape - The shape object to draw. * @param fillStyle - Defines style of the fill. * @param lineStyle - Defines style of the lines. * @param matrix - Transform applied to the points of the shape. - * @return - Returns geometry for chaining. + * @returns - Returns geometry for chaining. */ public drawShape( shape: IShape, @@ -222,10 +211,9 @@ export class GraphicsGeometry extends BatchGeometry /** * Draws the given shape to this Graphics object. Can be any of Circle, Rectangle, Ellipse, Line or Polygon. - * * @param {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} shape - The shape object to draw. * @param matrix - Transform applied to the points of the shape. - * @return - Returns geometry for chaining. + * @returns - Returns geometry for chaining. */ public drawHole(shape: IShape, matrix: Matrix = null): GraphicsGeometry { @@ -279,9 +267,8 @@ export class GraphicsGeometry extends BatchGeometry /** * Check to see if a point is contained within this geometry. - * * @param point - Point to check if it's contained. - * @return {Boolean} `true` if the point is contained within geometry. + * @returns {boolean} `true` if the point is contained within geometry. */ public containsPoint(point: IPointData): boolean { @@ -340,10 +327,8 @@ export class GraphicsGeometry extends BatchGeometry /** * Generates intermediate batch data. Either gets converted to drawCalls * or used to convert to batch objects directly by the Graphics object. - * - * @param allow32Indices - Allow using 32-bit indices for preventing artifacts when more that 65535 vertices */ - updateBatches(allow32Indices?: boolean): void + updateBatches(): void { if (!this.graphicsData.length) { @@ -454,16 +439,16 @@ export class GraphicsGeometry extends BatchGeometry return; } + const need32 = attrib > 0xffff; + // prevent allocation when length is same as buffer - if (this.indicesUint16 && this.indices.length === this.indicesUint16.length) + if (this.indicesUint16 && this.indices.length === this.indicesUint16.length + && need32 === (this.indicesUint16.BYTES_PER_ELEMENT > 2)) { this.indicesUint16.set(this.indices); } else { - const need32 - = attrib > 0xffff && allow32Indices; - this.indicesUint16 = need32 ? new Uint32Array(this.indices) : new Uint16Array(this.indices); } @@ -482,7 +467,6 @@ export class GraphicsGeometry extends BatchGeometry /** * Affinity check - * * @param styleA * @param styleB */ @@ -730,7 +714,10 @@ export class GraphicsGeometry extends BatchGeometry this._indexBuffer.update(this.indicesUint16); } - /** Process fill part of Graphics. */ + /** + * Process fill part of Graphics. + * @param data + */ protected processFill(data: GraphicsData): void { if (data.holes.length) @@ -745,7 +732,10 @@ export class GraphicsGeometry extends BatchGeometry } } - /** Process line part of Graphics. */ + /** + * Process line part of Graphics. + * @param data + */ protected processLine(data: GraphicsData): void { buildLine(data, this); @@ -756,7 +746,10 @@ export class GraphicsGeometry extends BatchGeometry } } - /** Process the holes data. */ + /** + * Process the holes data. + * @param holes + */ protected processHoles(holes: Array): void { for (let i = 0; i < holes.length; i++) @@ -777,77 +770,14 @@ export class GraphicsGeometry extends BatchGeometry protected calculateBounds(): void { const bounds = this._bounds; - const sequenceBounds = tmpBounds; - let curMatrix = Matrix.IDENTITY; - - this._bounds.clear(); - sequenceBounds.clear(); - - for (let i = 0; i < this.graphicsData.length; i++) - { - const data = this.graphicsData[i]; - const shape = data.shape; - const type = data.type; - const lineStyle = data.lineStyle; - const nextMatrix = data.matrix || Matrix.IDENTITY; - let lineWidth = 0.0; - - if (lineStyle && lineStyle.visible) - { - lineWidth = lineStyle.width * Math.max(0, lineStyle.alignment); - } - - if (curMatrix !== nextMatrix) - { - if (!sequenceBounds.isEmpty()) - { - bounds.addBoundsMatrix(sequenceBounds, curMatrix); - sequenceBounds.clear(); - } - curMatrix = nextMatrix; - } - - if (type === SHAPES.RECT || type === SHAPES.RREC) - { - const rect = shape as Rectangle | RoundedRectangle; - - sequenceBounds.addFramePad(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height, - lineWidth, lineWidth); - } - else if (type === SHAPES.CIRC) - { - const circle = shape as Circle; - - sequenceBounds.addFramePad(circle.x, circle.y, circle.x, circle.y, - circle.radius + lineWidth, circle.radius + lineWidth); - } - else if (type === SHAPES.ELIP) - { - const ellipse = shape as Ellipse; - - sequenceBounds.addFramePad(ellipse.x, ellipse.y, ellipse.x, ellipse.y, - ellipse.width + lineWidth, ellipse.height + lineWidth); - } - else - { - const poly = shape as Polygon; - // adding directly to the bounds - - bounds.addVerticesMatrix(curMatrix, (poly.points as any), 0, poly.points.length, lineWidth, lineWidth); - } - } - - if (!sequenceBounds.isEmpty()) - { - bounds.addBoundsMatrix(sequenceBounds, curMatrix); - } + bounds.clear(); + bounds.addVertexData((this.points as any), 0, this.points.length); bounds.pad(this.boundsPadding, this.boundsPadding); } /** * Transform points using matrix. - * * @param points - Points to transform * @param matrix - Transform matrix */ @@ -865,7 +795,6 @@ export class GraphicsGeometry extends BatchGeometry /** * Add colors. - * * @param colors - List of colors to add to * @param color - Color to add * @param alpha - Alpha to use @@ -882,7 +811,7 @@ export class GraphicsGeometry extends BatchGeometry // TODO use the premultiply bits Ivan added const rgb = (color >> 16) + (color & 0xff00) + ((color & 0xff) << 16); - const rgba = premultiplyTint(rgb, alpha); + const rgba = utils.premultiplyTint(rgb, alpha); colors.length = Math.max(colors.length, offset + size); @@ -892,7 +821,13 @@ export class GraphicsGeometry extends BatchGeometry } } - /** Add texture id that the shader/fragment wants to use. */ + /** + * Add texture id that the shader/fragment wants to use. + * @param textureIds + * @param id + * @param size + * @param offset + */ protected addTextureIds( textureIds: Array, id: number, @@ -909,7 +844,6 @@ export class GraphicsGeometry extends BatchGeometry /** * Generates the UVs for a shape. - * * @param verts - Vertices * @param uvs - UVs * @param texture - Reference to Texture @@ -959,7 +893,6 @@ export class GraphicsGeometry extends BatchGeometry /** * Modify uvs array according to position of texture region * Does not work with rotated or trimmed textures - * * @param uvs - array * @param texture - region * @param start - starting index for uvs diff --git a/packages/graphics/src/const.ts b/packages/graphics/src/const.ts index 7d54aa9ac75..4387871c62f 100644 --- a/packages/graphics/src/const.ts +++ b/packages/graphics/src/const.ts @@ -1,9 +1,7 @@ /** * Supported line joints in `PIXI.LineStyle` for graphics. - * * @see PIXI.Graphics#lineStyle * @see https://graphicdesign.stackexchange.com/questions/59018/what-is-a-bevel-join-of-two-lines-exactly-illustrator - * * @name LINE_JOIN * @memberof PIXI * @static @@ -12,7 +10,9 @@ * @property {string} BEVEL - 'bevel': add a square butt at each end of line segment and fill the triangle at turn * @property {string} ROUND - 'round': add an arc at the joint */ -export enum LINE_JOIN { +export enum LINE_JOIN +// eslint-disable-next-line @typescript-eslint/indent +{ MITER = 'miter', BEVEL = 'bevel', ROUND = 'round' @@ -20,9 +20,7 @@ export enum LINE_JOIN { /** * Support line caps in `PIXI.LineStyle` for graphics. - * * @see PIXI.Graphics#lineStyle - * * @name LINE_CAP * @memberof PIXI * @static @@ -31,13 +29,16 @@ export enum LINE_JOIN { * @property {string} ROUND - 'round': add semicircle at ends * @property {string} SQUARE - 'square': add square at end (like `BUTT` except more length at end) */ -export enum LINE_CAP { +export enum LINE_CAP +// eslint-disable-next-line @typescript-eslint/indent +{ BUTT = 'butt', ROUND = 'round', SQUARE = 'square' } -export interface IGraphicsCurvesSettings { +export interface IGraphicsCurvesSettings +{ adaptive: boolean; maxLength: number; minSegments: number; @@ -52,16 +53,15 @@ export interface IGraphicsCurvesSettings { * Graphics curves resolution settings. If `adaptive` flag is set to `true`, * the resolution is calculated based on the curve's length to ensure better visual quality. * Adaptive draw works with `bezierCurveTo` and `quadraticCurveTo`. - * * @static * @constant * @memberof PIXI * @name GRAPHICS_CURVES * @type {object} - * @property {boolean} adaptive=true - flag indicating if the resolution should be adaptive - * @property {number} maxLength=10 - maximal length of a single segment of the curve (if adaptive = false, ignored) - * @property {number} minSegments=8 - minimal number of segments in the curve (if adaptive = false, ignored) - * @property {number} maxSegments=2048 - maximal number of segments in the curve (if adaptive = false, ignored) + * @property {boolean} [adaptive=true] - flag indicating if the resolution should be adaptive + * @property {number} [maxLength=10] - maximal length of a single segment of the curve (if adaptive = false, ignored) + * @property {number} [minSegments=8] - minimal number of segments in the curve (if adaptive = false, ignored) + * @property {number} [maxSegments=2048] - maximal number of segments in the curve (if adaptive = false, ignored) */ export const GRAPHICS_CURVES: IGraphicsCurvesSettings = { adaptive: true, diff --git a/packages/graphics/src/index.ts b/packages/graphics/src/index.ts index b7674087687..2e398eb3a5e 100644 --- a/packages/graphics/src/index.ts +++ b/packages/graphics/src/index.ts @@ -21,7 +21,7 @@ import { } from './utils'; import type { BatchDrawCall } from '@pixi/core/'; import type { IShapeBuildCommand } from './utils/IShapeBuildCommand'; -import type { SHAPES } from '@pixi/math'; +import type { SHAPES } from '@pixi/core'; export const graphicsUtils = { buildPoly: buildPoly as IShapeBuildCommand, diff --git a/packages/graphics/src/styles/FillStyle.ts b/packages/graphics/src/styles/FillStyle.ts index 5db5da42ca0..6d1c72d31f9 100644 --- a/packages/graphics/src/styles/FillStyle.ts +++ b/packages/graphics/src/styles/FillStyle.ts @@ -1,16 +1,14 @@ import { Texture } from '@pixi/core'; -import type { Matrix } from '@pixi/math'; +import type { Matrix } from '@pixi/core'; /** * Fill style object for Graphics. - * * @memberof PIXI */ export class FillStyle { /** * The hex color value used when coloring the Graphics object. - * * @default 0xFFFFFF */ public color = 0xFFFFFF; @@ -20,14 +18,12 @@ export class FillStyle /** * The texture to be used for the fill. - * * @default 0 */ public texture: Texture = Texture.WHITE; /** * The transform applied to the texture. - * * @default null */ public matrix: Matrix = null; diff --git a/packages/graphics/src/styles/LineStyle.ts b/packages/graphics/src/styles/LineStyle.ts index e0d1abd6501..579bbd125d5 100644 --- a/packages/graphics/src/styles/LineStyle.ts +++ b/packages/graphics/src/styles/LineStyle.ts @@ -3,7 +3,6 @@ import { LINE_JOIN, LINE_CAP } from '../const'; /** * Represents the line style for Graphics. - * * @memberof PIXI */ export class LineStyle extends FillStyle @@ -19,7 +18,6 @@ export class LineStyle extends FillStyle /** * Line cap style. - * * @member {PIXI.LINE_CAP} * @default PIXI.LINE_CAP.BUTT */ @@ -27,7 +25,6 @@ export class LineStyle extends FillStyle /** * Line join style. - * * @member {PIXI.LINE_JOIN} * @default PIXI.LINE_JOIN.MITER */ diff --git a/packages/graphics/src/utils/ArcUtils.ts b/packages/graphics/src/utils/ArcUtils.ts index 0aa46d393d9..18eb160f316 100644 --- a/packages/graphics/src/utils/ArcUtils.ts +++ b/packages/graphics/src/utils/ArcUtils.ts @@ -1,7 +1,8 @@ import { GRAPHICS_CURVES } from '../const'; -import { PI_2 } from '@pixi/math'; +import { PI_2 } from '@pixi/core'; -interface IArcLikeShape { +interface IArcLikeShape +{ cx: number; cy: number; radius: number; @@ -12,7 +13,6 @@ interface IArcLikeShape { /** * Utilities for arc curves. - * * @private */ export class ArcUtils @@ -21,14 +21,14 @@ export class ArcUtils * The arcTo() method creates an arc/curve between two tangents on the canvas. * * "borrowed" from https://code.google.com/p/fxcanvas/ - thanks google! - * * @private * @param x1 - The x-coordinate of the beginning of the arc * @param y1 - The y-coordinate of the beginning of the arc * @param x2 - The x-coordinate of the end of the arc * @param y2 - The y-coordinate of the end of the arc * @param radius - The radius of the arc - * @return - If the arc length is valid, return center of circle, radius and other info otherwise `null`. + * @param points - + * @returns - If the arc length is valid, return center of circle, radius and other info otherwise `null`. */ static curveTo(x1: number, y1: number, x2: number, y2: number, radius: number, points: Array): IArcLikeShape { @@ -80,17 +80,16 @@ export class ArcUtils /* eslint-disable max-len */ /** * The arc method creates an arc/curve (used to create circles, or parts of circles). - * * @private - * @param startX - Start x location of arc - * @param startY - Start y location of arc + * @param _startX - Start x location of arc + * @param _startY - Start y location of arc * @param cx - The x-coordinate of the center of the circle * @param cy - The y-coordinate of the center of the circle * @param radius - The radius of the circle * @param startAngle - The starting angle, in radians (0 is at the 3 o'clock position * of the arc's circle) * @param endAngle - The ending angle, in radians - * @param anticlockwise - Specifies whether the drawing should be + * @param _anticlockwise - Specifies whether the drawing should be * counter-clockwise or clockwise. False is default, and indicates clockwise, while true * indicates counter-clockwise. * @param points - Collection of points to add to diff --git a/packages/graphics/src/utils/BatchPart.ts b/packages/graphics/src/utils/BatchPart.ts index 22753e5b144..fd51ba539ed 100644 --- a/packages/graphics/src/utils/BatchPart.ts +++ b/packages/graphics/src/utils/BatchPart.ts @@ -3,7 +3,6 @@ import type { FillStyle } from '../styles/FillStyle'; /** * A structure to hold interim batch objects for Graphics. - * * @memberof PIXI.graphicsUtils */ export class BatchPart @@ -19,7 +18,12 @@ export class BatchPart this.reset(); } - /** Begin batch part. */ + /** + * Begin batch part. + * @param style + * @param startIndex + * @param attribStart + */ public begin(style: LineStyle | FillStyle, startIndex: number, attribStart: number): void { this.reset(); @@ -28,7 +32,11 @@ export class BatchPart this.attribStart = attribStart; } - /** End batch part. */ + /** + * End batch part. + * @param endIndex + * @param endAttrib + */ public end(endIndex: number, endAttrib: number): void { this.attribSize = endAttrib - this.attribStart; diff --git a/packages/graphics/src/utils/BezierUtils.ts b/packages/graphics/src/utils/BezierUtils.ts index 92bce589029..345c1606c90 100644 --- a/packages/graphics/src/utils/BezierUtils.ts +++ b/packages/graphics/src/utils/BezierUtils.ts @@ -2,7 +2,6 @@ import { GRAPHICS_CURVES } from '../const'; /** * Utilities for bezier curves - * * @private */ export class BezierUtils @@ -11,7 +10,6 @@ export class BezierUtils * Calculate length of bezier curve. * Analytical solution is impossible, since it involves an integral that does not integrate in general. * Therefore numerical solution is used. - * * @private * @param fromX - Starting point x * @param fromY - Starting point y @@ -21,7 +19,7 @@ export class BezierUtils * @param cpY2 - Second Control point y * @param toX - Destination point x * @param toY - Destination point y - * @return - Length of bezier curve + * @returns - Length of bezier curve */ static curveLength( fromX: number, fromY: number, @@ -70,7 +68,6 @@ export class BezierUtils * Calculate the points for a bezier curve and then draws it. * * Ignored from docs since it is not directly exposed. - * * @ignore * @param cpX - Control point x * @param cpY - Control point y diff --git a/packages/graphics/src/utils/IShapeBuildCommand.ts b/packages/graphics/src/utils/IShapeBuildCommand.ts index e3ffc230145..14573617f42 100644 --- a/packages/graphics/src/utils/IShapeBuildCommand.ts +++ b/packages/graphics/src/utils/IShapeBuildCommand.ts @@ -1,7 +1,8 @@ import type { GraphicsData } from '../GraphicsData'; import type { GraphicsGeometry } from '../GraphicsGeometry'; -export interface IShapeBuildCommand { +export interface IShapeBuildCommand +{ build(graphicsData: GraphicsData): void; triangulate(graphicsData: GraphicsData, target: GraphicsGeometry): void; } diff --git a/packages/graphics/src/utils/QuadraticUtils.ts b/packages/graphics/src/utils/QuadraticUtils.ts index a6a88ef3b58..e9c0552ddb2 100644 --- a/packages/graphics/src/utils/QuadraticUtils.ts +++ b/packages/graphics/src/utils/QuadraticUtils.ts @@ -2,7 +2,6 @@ import { GRAPHICS_CURVES } from '../const'; /** * Utilities for quadratic curves. - * * @private */ export class QuadraticUtils @@ -11,7 +10,6 @@ export class QuadraticUtils * Calculate length of quadratic curve * @see {@link http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/} * for the detailed explanation of math behind this. - * * @private * @param fromX - x-coordinate of curve start point * @param fromY - y-coordinate of curve start point @@ -19,7 +17,7 @@ export class QuadraticUtils * @param cpY - y-coordinate of curve control point * @param toX - x-coordinate of curve end point * @param toY - y-coordinate of curve end point - * @return - Length of quadratic curve + * @returns - Length of quadratic curve */ static curveLength( fromX: number, fromY: number, @@ -53,7 +51,6 @@ export class QuadraticUtils /** * Calculate the points for a quadratic bezier curve and then draws it. * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c - * * @private * @param cpX - Control point x * @param cpY - Control point y diff --git a/packages/graphics/src/utils/buildCircle.ts b/packages/graphics/src/utils/buildCircle.ts index 863a297b767..0df0ad43f71 100644 --- a/packages/graphics/src/utils/buildCircle.ts +++ b/packages/graphics/src/utils/buildCircle.ts @@ -1,14 +1,13 @@ // for type only -import { SHAPES } from '@pixi/math'; +import { SHAPES } from '@pixi/core'; -import type { Circle, Ellipse, RoundedRectangle } from '@pixi/math'; +import type { Circle, Ellipse, RoundedRectangle } from '@pixi/core'; import type { IShapeBuildCommand } from './IShapeBuildCommand'; /** * Builds a circle to draw * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.WebGLGraphicsData} graphicsData - The graphics object to draw @@ -61,6 +60,13 @@ export const buildCircle: IShapeBuildCommand = { dy = halfHeight - ry; } + if (!(rx >= 0 && ry >= 0 && dx >= 0 && dy >= 0)) + { + points.length = 0; + + return; + } + // Choose a number of segments such that the maximum absolute deviation from the circle is approximately 0.029 const n = Math.ceil(2.3 * Math.sqrt(rx + ry)); const m = (n * 8) + (dx ? 4 : 0) + (dy ? 4 : 0); @@ -160,6 +166,11 @@ export const buildCircle: IShapeBuildCommand = { const verts = graphicsGeometry.points; const indices = graphicsGeometry.indices; + if (points.length === 0) + { + return; + } + let vertPos = verts.length / 2; const center = vertPos; diff --git a/packages/graphics/src/utils/buildLine.ts b/packages/graphics/src/utils/buildLine.ts index e228562adf3..0d2d5ec70ce 100644 --- a/packages/graphics/src/utils/buildLine.ts +++ b/packages/graphics/src/utils/buildLine.ts @@ -1,6 +1,6 @@ -import { Point, SHAPES } from '@pixi/math'; +import { Point, SHAPES } from '@pixi/core'; -import type { Polygon } from '@pixi/math'; +import type { Polygon } from '@pixi/core'; import type { GraphicsData } from '../GraphicsData'; import type { GraphicsGeometry } from '../GraphicsGeometry'; import { LINE_JOIN, LINE_CAP, GRAPHICS_CURVES } from '../const'; @@ -9,15 +9,17 @@ import { LINE_JOIN, LINE_CAP, GRAPHICS_CURVES } from '../const'; * Buffers vertices to draw a square cap. * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {number} x - X-coord of end point * @param {number} y - Y-coord of end point * @param {number} nx - X-coord of line normal pointing inside * @param {number} ny - Y-coord of line normal pointing inside + * @param {number} innerWeight - Weight of inner points + * @param {number} outerWeight - Weight of outer points + * @param {boolean} clockwise - Whether the cap is drawn clockwise * @param {Array} verts - vertex buffer - * @returns {} + * @returns {number} - no. of vertices pushed */ function square( x: number, @@ -67,7 +69,6 @@ function square( * Buffers vertices to draw an arc at the line joint or cap. * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {number} cx - X-coord of center @@ -172,7 +173,6 @@ function round( * Builds a line to draw using the polygon method. * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.GraphicsData} graphicsData - The graphics object containing all the necessary properties @@ -427,11 +427,7 @@ function buildNonNativeLine(graphicsData: GraphicsData, graphicsGeometry: Graphi { verts.push(x1 - (perpx * innerWeight), y1 - (perpy * innerWeight)); // first segment's inner vertex verts.push(x1 + (perpx * outerWeight), y1 + (perpy * outerWeight)); // first segment's outer vertex - if (style.join === LINE_JOIN.BEVEL || pdist / widthSquared > miterLimitSquared) - { - // Nothing needed - } - else if (style.join === LINE_JOIN.ROUND) + if (style.join === LINE_JOIN.ROUND) { if (clockwise) /* arc is outside */ { @@ -452,7 +448,7 @@ function buildNonNativeLine(graphicsData: GraphicsData, graphicsGeometry: Graphi ) + 2; } } - else + else if (style.join === LINE_JOIN.MITER && pdist / widthSquared <= miterLimitSquared) { if (clockwise) { @@ -540,7 +536,6 @@ function buildNonNativeLine(graphicsData: GraphicsData, graphicsGeometry: Graphi * Builds a line to draw using the gl.drawArrays(gl.LINES) method * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.GraphicsData} graphicsData - The graphics object containing all the necessary properties @@ -583,7 +578,6 @@ function buildNativeLine(graphicsData: GraphicsData, graphicsGeometry: GraphicsG * Builds a line to draw * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.GraphicsData} graphicsData - The graphics object containing all the necessary properties diff --git a/packages/graphics/src/utils/buildPoly.ts b/packages/graphics/src/utils/buildPoly.ts index d6d4d62d404..aac6e2cb51f 100644 --- a/packages/graphics/src/utils/buildPoly.ts +++ b/packages/graphics/src/utils/buildPoly.ts @@ -1,7 +1,7 @@ -import { earcut } from '@pixi/utils'; +import { utils } from '@pixi/core'; import type { IShapeBuildCommand } from './IShapeBuildCommand'; -import type { Polygon } from '@pixi/math'; +import type { Polygon } from '@pixi/core'; function fixOrientation(points: number[], hole = false) { @@ -45,7 +45,6 @@ function fixOrientation(points: number[], hole = false) * Builds a polygon to draw * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.WebGLGraphicsData} graphicsData - The graphics object containing all the necessary properties @@ -84,7 +83,7 @@ export const buildPoly: IShapeBuildCommand = { } // sort color - const triangles = earcut(points, holeArray, 2); + const triangles = utils.earcut(points, holeArray, 2); if (!triangles) { diff --git a/packages/graphics/src/utils/buildRectangle.ts b/packages/graphics/src/utils/buildRectangle.ts index 512f70507f4..6e23ef00e90 100644 --- a/packages/graphics/src/utils/buildRectangle.ts +++ b/packages/graphics/src/utils/buildRectangle.ts @@ -1,11 +1,10 @@ import type { IShapeBuildCommand } from './IShapeBuildCommand'; -import type { Rectangle } from '@pixi/math'; +import type { Rectangle } from '@pixi/core'; /** * Builds a rectangle to draw * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.WebGLGraphicsData} graphicsData - The graphics object containing all the necessary properties diff --git a/packages/graphics/src/utils/buildRoundedRectangle.ts b/packages/graphics/src/utils/buildRoundedRectangle.ts index 73ea13a39f4..f209ee51a79 100644 --- a/packages/graphics/src/utils/buildRoundedRectangle.ts +++ b/packages/graphics/src/utils/buildRoundedRectangle.ts @@ -1,95 +1,11 @@ -import { earcut } from '@pixi/utils'; - // for type only import type { IShapeBuildCommand } from './IShapeBuildCommand'; -import type { RoundedRectangle } from '@pixi/math'; -import { Graphics } from '../Graphics'; import { buildCircle } from './buildCircle'; -/** - * Calculate a single point for a quadratic bezier curve. - * Utility function used by quadraticBezierCurve. - * Ignored from docs since it is not directly exposed. - * - * @ignore - * @private - * @param {number} n1 - first number - * @param {number} n2 - second number - * @param {number} perc - percentage - * @return {number} the result - * - */ -function getPt(n1: number, n2: number, perc: number): number -{ - const diff = n2 - n1; - - return n1 + (diff * perc); -} - -/** - * Calculate the points for a quadratic bezier curve. (helper function..) - * Based on: https://stackoverflow.com/questions/785097/how-do-i-implement-a-bezier-curve-in-c - * - * Ignored from docs since it is not directly exposed. - * - * @ignore - * @private - * @param {number} fromX - Origin point x - * @param {number} fromY - Origin point x - * @param {number} cpX - Control point x - * @param {number} cpY - Control point y - * @param {number} toX - Destination point x - * @param {number} toY - Destination point y - * @param {number[]} [out=[]] - The output array to add points into. If not passed, a new array is created. - * @return {number[]} an array of points - */ -function quadraticBezierCurve( - fromX: number, fromY: number, - cpX: number, cpY: number, - toX: number, toY: number, - out: Array = []): Array -{ - const n = 20; - const points = out; - - let xa = 0; - let ya = 0; - let xb = 0; - let yb = 0; - let x = 0; - let y = 0; - - for (let i = 0, j = 0; i <= n; ++i) - { - j = i / n; - - // The Green Line - xa = getPt(fromX, cpX, j); - ya = getPt(fromY, cpY, j); - xb = getPt(cpX, toX, j); - yb = getPt(cpY, toY, j); - - // The Black Dot - x = getPt(xa, xb, j); - y = getPt(ya, yb, j); - - // Handle case when first curve points overlaps and earcut fails to triangulate - if (i === 0 && points[points.length - 2] === x && points[points.length - 1] === y) - { - continue; - } - - points.push(x, y); - } - - return points; -} - /** * Builds a rounded rectangle to draw * * Ignored from docs since it is not directly exposed. - * * @ignore * @private * @param {PIXI.WebGLGraphicsData} graphicsData - The graphics object containing all the necessary properties @@ -100,84 +16,11 @@ export const buildRoundedRectangle: IShapeBuildCommand = { build(graphicsData) { - if (Graphics.nextRoundedRectBehavior) - { - buildCircle.build(graphicsData); - - return; - } - - const rrectData = graphicsData.shape as RoundedRectangle; - const points = graphicsData.points; - const x = rrectData.x; - const y = rrectData.y; - const width = rrectData.width; - const height = rrectData.height; - - // Don't allow negative radius or greater than half the smallest width - const radius = Math.max(0, Math.min(rrectData.radius, Math.min(width, height) / 2)); - - points.length = 0; - - // No radius, do a simple rectangle - if (!radius) - { - points.push(x, y, - x + width, y, - x + width, y + height, - x, y + height); - } - else - { - quadraticBezierCurve(x, y + radius, - x, y, - x + radius, y, - points); - quadraticBezierCurve(x + width - radius, - y, x + width, y, - x + width, y + radius, - points); - quadraticBezierCurve(x + width, y + height - radius, - x + width, y + height, - x + width - radius, y + height, - points); - quadraticBezierCurve(x + radius, y + height, - x, y + height, - x, y + height - radius, - points); - } + buildCircle.build(graphicsData); }, triangulate(graphicsData, graphicsGeometry) { - if (Graphics.nextRoundedRectBehavior) - { - buildCircle.triangulate(graphicsData, graphicsGeometry); - - return; - } - - const points = graphicsData.points; - - const verts = graphicsGeometry.points; - const indices = graphicsGeometry.indices; - - const vecPos = verts.length / 2; - - const triangles = earcut(points, null, 2); - - for (let i = 0, j = triangles.length; i < j; i += 3) - { - indices.push(triangles[i] + vecPos); - // indices.push(triangles[i] + vecPos); - indices.push(triangles[i + 1] + vecPos); - // indices.push(triangles[i + 2] + vecPos); - indices.push(triangles[i + 2] + vecPos); - } - - for (let i = 0, j = points.length; i < j; i++) - { - verts.push(points[i], points[++i]); - } + buildCircle.triangulate(graphicsData, graphicsGeometry); }, }; diff --git a/packages/graphics/src/utils/index.ts b/packages/graphics/src/utils/index.ts index 35e3b3dfab6..e47579adbcc 100644 --- a/packages/graphics/src/utils/index.ts +++ b/packages/graphics/src/utils/index.ts @@ -1,6 +1,5 @@ /** * Generalized convenience utilities for Graphics. - * * @namespace graphicsUtils * @memberof PIXI */ @@ -24,16 +23,15 @@ export * from './QuadraticUtils'; export * from './BatchPart'; // for type only -import { BatchPart } from './BatchPart'; -import { SHAPES } from '@pixi/math'; -import { BatchDrawCall } from '@pixi/core'; -import { IShapeBuildCommand } from './IShapeBuildCommand'; +import type { BatchPart } from './BatchPart'; +import { SHAPES } from '@pixi/core'; +import type { BatchDrawCall } from '@pixi/core'; +import type { IShapeBuildCommand } from './IShapeBuildCommand'; /** * Map of fill commands for each shape type. - * * @memberof PIXI.graphicsUtils - * @member {Object} FILL_COMMANDS + * @member {object} FILL_COMMANDS */ export const FILL_COMMANDS: Record = { [SHAPES.POLY]: buildPoly, @@ -45,7 +43,6 @@ export const FILL_COMMANDS: Record = { /** * Batch pool, stores unused batches for preventing allocations. - * * @memberof PIXI.graphicsUtils * @member {Array} BATCH_POOL */ @@ -53,7 +50,6 @@ export const BATCH_POOL: Array = []; /** * Draw call pool, stores unused draw calls for preventing allocations. - * * @memberof PIXI.graphicsUtils * @member {Array} DRAW_CALL_POOL */ diff --git a/packages/graphics/test/Graphics.tests.ts b/packages/graphics/test/Graphics.tests.ts index a3848a0b035..37149c3a6b3 100644 --- a/packages/graphics/test/Graphics.tests.ts +++ b/packages/graphics/test/Graphics.tests.ts @@ -1,63 +1,55 @@ -import { Renderer, BatchRenderer, Texture } from '@pixi/core'; -import { Graphics, GRAPHICS_CURVES, FillStyle, LineStyle, graphicsUtils } from '@pixi/graphics'; +import { Texture, BLEND_MODES, Point, Matrix, SHAPES, Polygon, utils } from '@pixi/core'; +import { Graphics, GRAPHICS_CURVES, FillStyle, LineStyle, graphicsUtils, LINE_CAP } from '@pixi/graphics'; const { FILL_COMMANDS, buildLine } = graphicsUtils; -import { BLEND_MODES } from '@pixi/constants'; -import { Point, Matrix, SHAPES, Polygon } from '@pixi/math'; -import { skipHello } from '@pixi/utils'; -import sinon from 'sinon'; -import { expect } from 'chai'; +utils.skipHello(); -Renderer.registerPlugin('batch', BatchRenderer); - -skipHello(); - -describe('Graphics', function () +describe('Graphics', () => { - describe('constructor', function () + describe('constructor', () => { - it('should set defaults', function () + it('should set defaults', () => { const graphics = new Graphics(); - expect(graphics.fill.color).to.be.equals(0xFFFFFF); - expect(graphics.fill.alpha).to.be.equals(1); - expect(graphics.line.width).to.be.equals(0); - expect(graphics.line.color).to.be.equals(0); - expect(graphics.tint).to.be.equals(0xFFFFFF); - expect(graphics.blendMode).to.be.equals(BLEND_MODES.NORMAL); + expect(graphics.fill.color).toEqual(0xFFFFFF); + expect(graphics.fill.alpha).toEqual(1); + expect(graphics.line.width).toEqual(0); + expect(graphics.line.color).toEqual(0); + expect(graphics.tint).toEqual(0xFFFFFF); + expect(graphics.blendMode).toEqual(BLEND_MODES.NORMAL); }); }); - describe('lineStyle', function () + describe('lineStyle', () => { - it('should support a list of parameters', function () + it('should support a list of parameters', () => { const graphics = new Graphics(); graphics.lineStyle(1, 0xff0000, 0.5, 1, true); - expect(graphics.line.width).to.equal(1); - expect(graphics.line.color).to.equal(0xff0000); - expect(graphics.line.alignment).to.equal(1); - expect(graphics.line.alpha).to.equal(0.5); - expect(graphics.line.native).to.equal(true); + expect(graphics.line.width).toEqual(1); + expect(graphics.line.color).toEqual(0xff0000); + expect(graphics.line.alignment).toEqual(1); + expect(graphics.line.alpha).toEqual(0.5); + expect(graphics.line.native).toEqual(true); graphics.destroy(); }); - it('should default color to black if texture not present and white if present', function () + it('should default color to black if texture not present and white if present', () => { const graphics = new Graphics(); graphics.lineStyle(1); - expect(graphics.line.color).to.equal(0x0); + expect(graphics.line.color).toEqual(0x0); graphics.lineTextureStyle({ texture: Texture.WHITE, width: 1 }); - expect(graphics.line.color).to.equal(0xFFFFFF); + expect(graphics.line.color).toEqual(0xFFFFFF); graphics.destroy(); }); - it('should support object parameter', function () + it('should support object parameter', () => { const graphics = new Graphics(); @@ -69,33 +61,33 @@ describe('Graphics', function () native: true, }); - expect(graphics.line.width).to.equal(1); - expect(graphics.line.color).to.equal(0xff0000); - expect(graphics.line.alignment).to.equal(1); - expect(graphics.line.alpha).to.equal(0.5); - expect(graphics.line.native).to.equal(true); - expect(graphics.line.visible).to.equal(true); + expect(graphics.line.width).toEqual(1); + expect(graphics.line.color).toEqual(0xff0000); + expect(graphics.line.alignment).toEqual(1); + expect(graphics.line.alpha).toEqual(0.5); + expect(graphics.line.native).toEqual(true); + expect(graphics.line.visible).toEqual(true); graphics.lineStyle(); - expect(graphics.line.width).to.equal(0); - expect(graphics.line.color).to.equal(0); - expect(graphics.line.alignment).to.equal(0.5); - expect(graphics.line.alpha).to.equal(1); - expect(graphics.line.native).to.equal(false); - expect(graphics.line.visible).to.equal(false); + expect(graphics.line.width).toEqual(0); + expect(graphics.line.color).toEqual(0); + expect(graphics.line.alignment).toEqual(0.5); + expect(graphics.line.alpha).toEqual(1); + expect(graphics.line.native).toEqual(false); + expect(graphics.line.visible).toEqual(false); graphics.destroy(); }); }); - describe('lineTextureStyle', function () + describe('lineTextureStyle', () => { - it('should support object parameter', function () + it('should support object parameter', () => { const graphics = new Graphics(); const matrix = new Matrix(); - const texture = Texture.BLACK; + const texture = Texture.WHITE; graphics.lineTextureStyle({ width: 1, @@ -107,33 +99,33 @@ describe('Graphics', function () native: true, }); - expect(graphics.line.width).to.equal(1); - expect(graphics.line.texture).to.equal(texture); - expect(graphics.line.matrix).to.be.ok; - expect(graphics.line.color).to.equal(0xff0000); - expect(graphics.line.alignment).to.equal(1); - expect(graphics.line.alpha).to.equal(0.5); - expect(graphics.line.native).to.equal(true); - expect(graphics.line.visible).to.equal(true); + expect(graphics.line.width).toEqual(1); + expect(graphics.line.texture).toEqual(texture); + expect(graphics.line.matrix).toBeTruthy(); + expect(graphics.line.color).toEqual(0xff0000); + expect(graphics.line.alignment).toEqual(1); + expect(graphics.line.alpha).toEqual(0.5); + expect(graphics.line.native).toEqual(true); + expect(graphics.line.visible).toEqual(true); graphics.lineTextureStyle(); - expect(graphics.line.width).to.equal(0); - expect(graphics.line.texture).to.equal(Texture.WHITE); - expect(graphics.line.matrix).to.equal(null); - expect(graphics.line.color).to.equal(0); - expect(graphics.line.alignment).to.equal(0.5); - expect(graphics.line.alpha).to.equal(1); - expect(graphics.line.native).to.equal(false); - expect(graphics.line.visible).to.equal(false); + expect(graphics.line.width).toEqual(0); + expect(graphics.line.texture).toEqual(Texture.WHITE); + expect(graphics.line.matrix).toEqual(null); + expect(graphics.line.color).toEqual(0); + expect(graphics.line.alignment).toEqual(0.5); + expect(graphics.line.alpha).toEqual(1); + expect(graphics.line.native).toEqual(false); + expect(graphics.line.visible).toEqual(false); graphics.destroy(); }); }); - describe('beginTextureFill', function () + describe('beginTextureFill', () => { - it('should pass texture to batches', function () + it('should pass texture to batches', () => { const graphics = new Graphics(); const canvas1 = document.createElement('canvas'); @@ -157,26 +149,26 @@ describe('Graphics', function () const batches = graphics.geometry.batches; - expect(batches.length).to.equal(2); - expect(batches[0].style.texture).to.equal(validTex1); - expect(batches[1].style.texture).to.equal(validTex2); + expect(batches.length).toEqual(2); + expect(batches[0].style.texture).toEqual(validTex1); + expect(batches[1].style.texture).toEqual(validTex2); }); }); - describe('utils', function () + describe('utils', () => { - it('FILL_COMMADS should be filled', function () + it('FILL_COMMADS should be filled', () => { - expect(FILL_COMMANDS).to.not.be.null; + expect(FILL_COMMANDS).not.toBeNull(); - expect(FILL_COMMANDS[SHAPES.POLY]).to.not.be.null; - expect(FILL_COMMANDS[SHAPES.CIRC]).to.not.be.null; - expect(FILL_COMMANDS[SHAPES.ELIP]).to.not.be.null; - expect(FILL_COMMANDS[SHAPES.RECT]).to.not.be.null; - expect(FILL_COMMANDS[SHAPES.RREC]).to.not.be.null; + expect(FILL_COMMANDS[SHAPES.POLY]).not.toBeNull(); + expect(FILL_COMMANDS[SHAPES.CIRC]).not.toBeNull(); + expect(FILL_COMMANDS[SHAPES.ELIP]).not.toBeNull(); + expect(FILL_COMMANDS[SHAPES.RECT]).not.toBeNull(); + expect(FILL_COMMANDS[SHAPES.RREC]).not.toBeNull(); }); - it('buildLine should execute without throws', function () + it('buildLine should execute without throws', () => { const graphics = new Graphics(); @@ -187,65 +179,65 @@ describe('Graphics', function () const data = geometry.graphicsData[0]; // native = false - expect(function () { buildLine(data, geometry); }).to.not.throw(); + expect(() => { buildLine(data, geometry); }).not.toThrowError(); data.lineStyle.native = true; // native = true - expect(function () { buildLine(data, geometry); }).to.not.throw(); + expect(() => { buildLine(data, geometry); }).not.toThrowError(); }); }); - describe('lineTo', function () + describe('lineTo', () => { - it('should return correct bounds - north', function () + it('should return correct bounds - north', () => { const graphics = new Graphics(); - graphics.lineStyle(1); + graphics.lineStyle({ width: 1, cap: LINE_CAP.SQUARE }); graphics.moveTo(0, 0); graphics.lineTo(0, 10); - expect(graphics.width).to.be.closeTo(1, 0.0001); - expect(graphics.height).to.be.closeTo(11, 0.0001); + expect(graphics.width).toBeCloseTo(1, 0.0001); + expect(graphics.height).toBeCloseTo(11, 0.0001); }); - it('should return correct bounds - south', function () + it('should return correct bounds - south', () => { const graphics = new Graphics(); graphics.moveTo(0, 0); - graphics.lineStyle(1); + graphics.lineStyle({ width: 1, cap: LINE_CAP.SQUARE }); graphics.lineTo(0, -10); - expect(graphics.width).to.be.closeTo(1, 0.0001); - expect(graphics.height).to.be.closeTo(11, 0.0001); + expect(graphics.width).toBeCloseTo(1, 0.0001); + expect(graphics.height).toBeCloseTo(11, 0.0001); }); - it('should return correct bounds - east', function () + it('should return correct bounds - east', () => { const graphics = new Graphics(); graphics.moveTo(0, 0); - graphics.lineStyle(1); + graphics.lineStyle({ width: 1, cap: LINE_CAP.SQUARE }); graphics.lineTo(10, 0); - expect(graphics.height).to.be.closeTo(1, 0.0001); - expect(graphics.width).to.be.closeTo(11, 0.0001); + expect(graphics.height).toBeCloseTo(1, 0.0001); + expect(graphics.width).toBeCloseTo(11, 0.0001); }); - it('should return correct bounds - west', function () + it('should return correct bounds - west', () => { const graphics = new Graphics(); graphics.moveTo(0, 0); - graphics.lineStyle(1); + graphics.lineStyle({ width: 1, cap: LINE_CAP.SQUARE }); graphics.lineTo(-10, 0); - expect(graphics.height).to.be.closeTo(1, 0.0001); - expect(graphics.width).to.be.closeTo(11, 0.0001); + expect(graphics.height).toBeCloseTo(1, 0.0001); + expect(graphics.width).toBeCloseTo(11, 0.0001); }); - it('should return correct bounds when stacked with circle', function () + it('should return correct bounds when stacked with circle', () => { const graphics = new Graphics(); @@ -253,18 +245,18 @@ describe('Graphics', function () graphics.drawCircle(50, 50, 50); graphics.endFill(); - expect(graphics.width).to.be.equals(100); - expect(graphics.height).to.be.equals(100); + expect(graphics.width).toEqual(100); + expect(graphics.height).toEqual(100); graphics.lineStyle(20, 0); graphics.moveTo(25, 50); graphics.lineTo(75, 50); - expect(graphics.width).to.be.equals(100); - expect(graphics.height).to.be.equals(100); + expect(graphics.width).toEqual(100); + expect(graphics.height).toEqual(100); }); - it('should return correct bounds when square', function () + it('should return correct bounds when square', () => { const graphics = new Graphics(); @@ -275,11 +267,11 @@ describe('Graphics', function () graphics.lineTo(0, 50); graphics.lineTo(0, 0); - expect(graphics.width).to.be.equals(70); - expect(graphics.height).to.be.equals(70); + expect(graphics.width).toEqual(70); + expect(graphics.height).toEqual(70); }); - it('should ignore duplicate calls', function () + it('should ignore duplicate calls', () => { const graphics = new Graphics(); @@ -288,13 +280,13 @@ describe('Graphics', function () graphics.lineTo(10, 0); graphics.lineTo(10, 0); - expect(graphics.currentPath.points).to.deep.equal([0, 0, 10, 0]); + expect(graphics.currentPath.points).toEqual([0, 0, 10, 0]); }); }); - describe('containsPoint', function () + describe('containsPoint', () => { - it('should return true when point inside a standard shape', function () + it('should return true when point inside a standard shape', () => { const point = new Point(1, 1); const graphics = new Graphics(); @@ -302,10 +294,10 @@ describe('Graphics', function () graphics.beginFill(0); graphics.drawRect(0, 0, 10, 10); - expect(graphics.containsPoint(point)).to.be.true; + expect(graphics.containsPoint(point)).toBe(true); }); - it('should return false when point outside a standard shape', function () + it('should return false when point outside a standard shape', () => { const point = new Point(20, 20); const graphics = new Graphics(); @@ -313,10 +305,10 @@ describe('Graphics', function () graphics.beginFill(0); graphics.drawRect(0, 0, 10, 10); - expect(graphics.containsPoint(point)).to.be.false; + expect(graphics.containsPoint(point)).toBe(false); }); - it('should return true when point inside just lines', function () + it('should return true when point inside just lines', () => { const point = new Point(1, 1); const graphics = new Graphics(); @@ -329,10 +321,10 @@ describe('Graphics', function () graphics.lineTo(0, 0); graphics.closePath(); - expect(graphics.containsPoint(point)).to.be.true; + expect(graphics.containsPoint(point)).toBe(true); }); - it('should return false when point outside just lines', function () + it('should return false when point outside just lines', () => { const point = new Point(20, 20); const graphics = new Graphics(); @@ -344,20 +336,20 @@ describe('Graphics', function () graphics.lineTo(0, 0); graphics.closePath(); - expect(graphics.containsPoint(point)).to.be.false; + expect(graphics.containsPoint(point)).toBe(false); }); - it('should return false when no fill', function () + it('should return false when no fill', () => { const point = new Point(1, 1); const graphics = new Graphics(); graphics.drawRect(0, 0, 10, 10); - expect(graphics.containsPoint(point)).to.be.false; + expect(graphics.containsPoint(point)).toBe(false); }); - it('should return false with hole', function () + it('should return false with hole', () => { const point1 = new Point(1, 1); const point2 = new Point(5, 5); @@ -375,11 +367,11 @@ describe('Graphics', function () .lineTo(2, 8) .endHole(); - expect(graphics.containsPoint(point1)).to.be.true; - expect(graphics.containsPoint(point2)).to.be.false; + expect(graphics.containsPoint(point1)).toBe(true); + expect(graphics.containsPoint(point2)).toBe(false); }); - it('should handle extra shapes in holes', function () + it('should handle extra shapes in holes', () => { const graphics = new Graphics(); @@ -406,14 +398,14 @@ describe('Graphics', function () .lineTo(5, 7) .endFill(); - expect(graphics.containsPoint(new Point(1, 1))).to.be.true; - expect(graphics.containsPoint(new Point(4, 4))).to.be.true; - expect(graphics.containsPoint(new Point(4, 6))).to.be.false; - expect(graphics.containsPoint(new Point(6, 4))).to.be.false; - expect(graphics.containsPoint(new Point(6, 6))).to.be.true; + expect(graphics.containsPoint(new Point(1, 1))).toBe(true); + expect(graphics.containsPoint(new Point(4, 4))).toBe(true); + expect(graphics.containsPoint(new Point(4, 6))).toBe(false); + expect(graphics.containsPoint(new Point(6, 4))).toBe(false); + expect(graphics.containsPoint(new Point(6, 6))).toBe(true); }); - it('should take a matrix into account', function () + it('should take a matrix into account', () => { const g = new Graphics(); const m = new Matrix(); @@ -428,16 +420,16 @@ describe('Graphics', function () g.setMatrix(null); g.drawRect(30, 40, 10, 10); - expect(g.containsPoint(new Point(5, 5))).to.be.false; - expect(g.containsPoint(new Point(5, 105))).to.be.true; - expect(g.containsPoint(new Point(205, 5))).to.be.true; - expect(g.containsPoint(new Point(35, 45))).to.be.true; + expect(g.containsPoint(new Point(5, 5))).toBe(false); + expect(g.containsPoint(new Point(5, 105))).toBe(true); + expect(g.containsPoint(new Point(205, 5))).toBe(true); + expect(g.containsPoint(new Point(35, 45))).toBe(true); }); }); - describe('chaining', function () + describe('chaining', () => { - it('should chain draw commands', function () + it('should chain draw commands', () => { // complex drawing #1: draw triangle, rounder rect and an arc (issue #3433) const graphics = new Graphics().beginFill(0xFF3300) @@ -449,7 +441,7 @@ describe('Graphics', function () .beginHole() .endHole() .quadraticCurveTo(1, 1, 1, 1) - .bezierCurveTo(1, 1, 1, 1) + .bezierCurveTo(1, 1, 1, 1, 1, 1) .arcTo(1, 1, 1, 1, 1) .arc(1, 1, 1, 1, 1, false) .drawRect(1, 1, 1, 1) @@ -459,108 +451,116 @@ describe('Graphics', function () .drawPolygon([1, 1, 1, 1, 1, 1]) .clear(); - expect(graphics).to.be.not.null; + expect(graphics).not.toBeNull(); }); }); - describe('drawPolygon', function () + describe('drawPolygon', () => { - before(function () + let numbers: number[]; + let points: Point[]; + let poly: Polygon; + + beforeAll(() => { - this.numbers = [0, 0, 10, 10, 20, 20]; - this.points = [new Point(0, 0), new Point(10, 10), new Point(20, 20)]; - this.poly = new Polygon(this.points); + numbers = [0, 0, 10, 10, 20, 20]; + points = [new Point(0, 0), new Point(10, 10), new Point(20, 20)]; + poly = new Polygon(points); }); - it('should support polygon argument', function () + it('should support polygon argument', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); - graphics.drawPolygon(this.poly); + graphics.drawPolygon(poly); - expect(graphics.geometry.graphicsData[0]).to.be.not.null; + expect(graphics.geometry.graphicsData[0]).not.toBeNull(); - const result = graphics.geometry.graphicsData[0].shape.points; + const result = (graphics.geometry.graphicsData[0].shape as Polygon).points; - expect(result).to.deep.equals(this.numbers); + expect(result).toEqual(numbers); }); - it('should support array of numbers', function () + it('should support array of numbers', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); - graphics.drawPolygon(this.numbers); + graphics.drawPolygon(numbers); - expect(graphics.geometry.graphicsData[0]).to.be.not.null; + expect(graphics.geometry.graphicsData[0]).not.toBeNull(); - const result = graphics.geometry.graphicsData[0].shape.points; + const result = (graphics.geometry.graphicsData[0].shape as Polygon).points; - expect(result).to.deep.equals(this.numbers); + expect(result).toEqual(numbers); }); - it('should support array of points', function () + it('should support array of points', () => { const graphics = new Graphics(); - graphics.drawPolygon(this.points); + graphics.drawPolygon(points); - expect(graphics.geometry.graphicsData[0]).to.be.not.null; + expect(graphics.geometry.graphicsData[0]).not.toBeNull(); - const result = graphics.geometry.graphicsData[0].shape.points; + const result = (graphics.geometry.graphicsData[0].shape as Polygon).points; - expect(result).to.deep.equals(this.numbers); + expect(result).toEqual(numbers); }); - it('should support flat arguments of numbers', function () + it('should support flat arguments of numbers', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); - graphics.drawPolygon(...this.numbers); + graphics.drawPolygon(...numbers); - expect(graphics.geometry.graphicsData[0]).to.be.not.null; + expect(graphics.geometry.graphicsData[0]).not.toBeNull(); - const result = graphics.geometry.graphicsData[0].shape.points; + const result = (graphics.geometry.graphicsData[0].shape as Polygon).points; - expect(result).to.deep.equals(this.numbers); + expect(result).toEqual(numbers); }); - it('should support flat arguments of points', function () + it('should support flat arguments of points', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); - graphics.drawPolygon(...this.points); + graphics.drawPolygon(...points); - expect(graphics.geometry.graphicsData[0]).to.be.not.null; + expect(graphics.geometry.graphicsData[0]).not.toBeNull(); - const result = graphics.geometry.graphicsData[0].shape.points; + const result = (graphics.geometry.graphicsData[0].shape as Polygon).points; - expect(result).to.deep.equals(this.numbers); + expect(result).toEqual(numbers); }); }); - describe('drawing same rectangle with drawPolygon and drawRect', function () + describe('drawing same rectangle with drawPolygon and drawRect', () => { - before(function () + let width: number; + let height: number; + let points: Point[]; + + beforeAll(() => { - this.width = 100; - this.height = 100; - this.points = [ + width = 100; + height = 100; + points = [ new Point(0, 0), - new Point(this.width, 0), - new Point(this.width, this.height), - new Point(0, this.height) + new Point(width, 0), + new Point(width, height), + new Point(0, height) ]; }); - it('should have the same bounds for any line alignment value', function () + it('should have the same bounds for any line alignment value', () => { const polyGraphics = new Graphics(); const rectGraphics = new Graphics(); @@ -575,39 +575,39 @@ describe('Graphics', function () polyGraphics.beginFill(0x0000ff); polyGraphics.lineStyle(lineWidth, 0xff0000, 1, lineAlignment); - polyGraphics.drawPolygon(this.points); + polyGraphics.drawPolygon(points); polyGraphics.endFill(); rectGraphics.beginFill(0x0000ff); rectGraphics.lineStyle(lineWidth, 0xff0000, 1, lineAlignment); - rectGraphics.drawRect(0, 0, this.width, this.height); + rectGraphics.drawRect(0, 0, width, height); rectGraphics.endFill(); const polyBounds = polyGraphics.getBounds(); const rectBounds = rectGraphics.getBounds(); - expect(polyBounds.x).to.equal(rectBounds.x); - expect(polyBounds.y).to.equal(rectBounds.y); - expect(polyBounds.width).to.equal(rectBounds.width); - expect(polyBounds.height).to.equal(rectBounds.height); + expect(polyBounds.x).toEqual(rectBounds.x); + expect(polyBounds.y).toEqual(rectBounds.y); + expect(polyBounds.width).toEqual(rectBounds.width); + expect(polyBounds.height).toEqual(rectBounds.height); }); }); }); - describe('arc', function () + describe('arc', () => { - it('should draw an arc', function () + it('should draw an arc', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); - expect(() => graphics.arc(100, 30, 20, 0, Math.PI)).to.not.throw(); + expect(() => graphics.arc(100, 30, 20, 0, Math.PI)).not.toThrowError(); - expect(graphics.currentPath).to.be.not.null; + expect(graphics.currentPath).not.toBeNull(); }); - it('should not throw with other shapes', function () + it('should not throw with other shapes', () => { // complex drawing #1: draw triangle, rounder rect and an arc (issue #3433) const graphics = new Graphics(); @@ -631,70 +631,72 @@ describe('Graphics', function () graphics.beginFill(); graphics.lineStyle(4, 0x00ff00, 1); - expect(() => graphics.arc(300, 100, 20, 0, Math.PI)).to.not.throw(); + expect(() => graphics.arc(300, 100, 20, 0, Math.PI)).not.toThrowError(); }); - it('should do nothing when startAngle and endAngle are equal', function () + it('should do nothing when startAngle and endAngle are equal', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); graphics.arc(0, 0, 10, 0, 0); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); }); - it('should do nothing if sweep equals zero', function () + it('should do nothing if sweep equals zero', () => { const graphics = new Graphics(); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); graphics.arc(0, 0, 10, 10, 10); - expect(graphics.currentPath).to.be.null; + expect(graphics.currentPath).toBeNull(); }); }); - describe('_calculateBounds', function () + describe('_calculateBounds', () => { - it('should only call updateLocalBounds once when not empty', function () + it('should only call updateLocalBounds once when not empty', () => { const graphics = new Graphics(); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); - const spy = sinon.spy(graphics.geometry, 'calculateBounds'); + const spy = jest.spyOn(graphics.geometry, 'calculateBounds' as any); - graphics._calculateBounds(); + graphics['_calculateBounds'](); - expect(spy).to.have.been.calledOnce; + expect(spy).toHaveBeenCalledOnce(); - graphics._calculateBounds(); + graphics['_calculateBounds'](); - expect(spy).to.have.been.calledOnce; + expect(spy).toHaveBeenCalledOnce(); }); - it('should not call updateLocalBounds when empty', function () + it('should not call updateLocalBounds when empty', () => { const graphics = new Graphics(); - const spy = sinon.spy(graphics.geometry, 'calculateBounds'); + const spy = jest.spyOn(graphics.geometry, 'calculateBounds' as any); - graphics._calculateBounds(); + graphics['_calculateBounds'](); - expect(spy).to.not.have.been.called; + expect(spy).not.toBeCalled(); - graphics._calculateBounds(); + graphics['_calculateBounds'](); - expect(spy).to.not.have.been.called; + expect(spy).not.toBeCalled(); }); }); - describe('getBounds', function () + describe('getBounds', () => { - it('should use getBounds without stroke', function () + it('should use getBounds without stroke', () => { const graphics = new Graphics(); @@ -702,13 +704,13 @@ describe('Graphics', function () const { x, y, width, height } = graphics.getBounds(); - expect(x).to.equal(10); - expect(y).to.equal(20); - expect(width).to.equal(100); - expect(height).to.equal(200); + expect(x).toEqual(10); + expect(y).toEqual(20); + expect(width).toEqual(100); + expect(height).toEqual(200); }); - it('should use getBounds with stroke', function () + it('should use getBounds with stroke', () => { const graphics = new Graphics(); @@ -719,25 +721,25 @@ describe('Graphics', function () const { x, y, width, height } = graphics.getBounds(); - expect(x).to.equal(8); - expect(y).to.equal(18); - expect(width).to.equal(104); - expect(height).to.equal(204); + expect(x).toEqual(8); + expect(y).toEqual(18); + expect(width).toEqual(104); + expect(height).toEqual(204); }); - it('should be zero for empty Graphics', function () + it('should be zero for empty Graphics', () => { const graphics = new Graphics(); const { x, y, width, height } = graphics.getBounds(); - expect(x).to.equal(0); - expect(y).to.equal(0); - expect(width).to.equal(0); - expect(height).to.equal(0); + expect(x).toEqual(0); + expect(y).toEqual(0); + expect(width).toEqual(0); + expect(height).toEqual(0); }); - it('should be zero after clear', function () + it('should be zero after clear', () => { const graphics = new Graphics(); @@ -749,13 +751,13 @@ describe('Graphics', function () const { x, y, width, height } = graphics.getBounds(); - expect(x).to.equal(0); - expect(y).to.equal(0); - expect(width).to.equal(0); - expect(height).to.equal(0); + expect(x).toEqual(0); + expect(y).toEqual(0); + expect(width).toEqual(0); + expect(height).toEqual(0); }); - it('should be equal of childs bounds when empty', function () + it('should be equal of childs bounds when empty', () => { const graphics = new Graphics(); const child = new Graphics(); @@ -768,16 +770,16 @@ describe('Graphics', function () const { x, y, width, height } = graphics.getBounds(); - expect(x).to.equal(10); - expect(y).to.equal(20); - expect(width).to.equal(100); - expect(height).to.equal(200); + expect(x).toEqual(10); + expect(y).toEqual(20); + expect(width).toEqual(100); + expect(height).toEqual(200); }); }); - describe('startPoly', function () + describe('startPoly', () => { - it('should fill two triangles', function () + it('should fill two triangles', () => { const graphics = new Graphics(); @@ -795,12 +797,12 @@ describe('Graphics', function () const data = graphics.geometry.graphicsData; - expect(data.length).to.equals(2); - expect(data[0].shape.points).to.eql([50, 50, 250, 50, 100, 100, 50, 50]); - expect(data[1].shape.points).to.eql([250, 50, 450, 50, 300, 100, 250, 50]); + expect(data.length).toEqual(2); + expect((data[0].shape as Polygon).points).toEqual([50, 50, 250, 50, 100, 100, 50, 50]); + expect((data[1].shape as Polygon).points).toEqual([250, 50, 450, 50, 300, 100, 250, 50]); }); - it('should honor lineStyle break', function () + it('should honor lineStyle break', () => { const graphics = new Graphics(); @@ -814,13 +816,13 @@ describe('Graphics', function () const data = graphics.geometry.graphicsData; - expect(data.length).to.equals(2); - expect(data[0].shape.points).to.eql([50, 50, 250, 50]); - expect(data[1].shape.points).to.eql([250, 50, 100, 100, 50, 50]); + expect(data.length).toEqual(2); + expect((data[0].shape as Polygon).points).toEqual([50, 50, 250, 50]); + expect((data[1].shape as Polygon).points).toEqual([250, 50, 100, 100, 50, 50]); }); }); - describe('should support adaptive curves', function () + describe('should support adaptive curves', () => { const defMode = GRAPHICS_CURVES.adaptive; const defMaxLen = GRAPHICS_CURVES.maxLength; @@ -834,19 +836,19 @@ describe('Graphics', function () graphics.quadraticCurveTo(600, 510, 590, 500); graphics.endFill(); - const pointsLen = graphics.geometry.graphicsData[0].shape.points.length / 2; + const pointsLen = (graphics.geometry.graphicsData[0].shape as Polygon).points.length / 2; const arcLen = Math.PI / 2 * Math.sqrt(200); const estimate = Math.ceil(arcLen / myMaxLen) + 1; - expect(pointsLen).to.be.closeTo(estimate, 2.0); + expect(pointsLen).toBeCloseTo(estimate, 2.0); GRAPHICS_CURVES.adaptive = defMode; GRAPHICS_CURVES.maxLength = defMaxLen; }); - describe('geometry', function () + describe('geometry', () => { - it('validateBatching should return false if any of textures is invalid', function () + it('validateBatching should return false if any of textures is invalid', () => { const graphics = new Graphics(); const invalidTex = Texture.EMPTY; @@ -859,10 +861,10 @@ describe('Graphics', function () const geometry = graphics.geometry; - expect(geometry.validateBatching()).to.be.false; + expect(geometry['validateBatching']()).toBe(false); }); - it('validateBatching should return true if all textures is valid', function () + it('validateBatching should return true if all textures is valid', () => { const graphics = new Graphics(); const validTex = Texture.WHITE; @@ -874,19 +876,19 @@ describe('Graphics', function () const geometry = graphics.geometry; - expect(geometry.validateBatching()).to.be.true; + expect(geometry['validateBatching']()).toBe(true); }); - it('should be batchable if graphicsData is empty', function () + it('should be batchable if graphicsData is empty', () => { const graphics = new Graphics(); const geometry = graphics.geometry; geometry.updateBatches(); - expect(geometry.batchable).to.be.true; + expect(geometry.batchable).toBe(true); }); - it('_compareStyles should return true for identical styles', function () + it('_compareStyles should return true for identical styles', () => { const graphics = new Graphics(); const geometry = graphics.geometry; @@ -899,7 +901,7 @@ describe('Graphics', function () const second = first.clone(); - expect(geometry._compareStyles(first, second)).to.be.true; + expect(geometry['_compareStyles'](first, second)).toBe(true); const firstLine = new LineStyle(); @@ -909,10 +911,10 @@ describe('Graphics', function () const secondLine = firstLine.clone(); - expect(geometry._compareStyles(firstLine, secondLine)).to.be.true; + expect(geometry['_compareStyles'](firstLine, secondLine)).toBe(true); }); - it('should be 1 batch for same styles', function () + it('should be 1 batch for same styles', () => { const graphics = new Graphics(); @@ -923,10 +925,10 @@ describe('Graphics', function () const geometry = graphics.geometry; geometry.updateBatches(); - expect(geometry.batches).to.have.lengthOf(1); + expect(geometry.batches).toHaveLength(1); }); - it('should be 2 batches for 2 different styles', function () + it('should be 2 batches for 2 different styles', () => { const graphics = new Graphics(); @@ -944,10 +946,10 @@ describe('Graphics', function () const geometry = graphics.geometry; geometry.updateBatches(); - expect(geometry.batches).to.have.lengthOf(2); + expect(geometry.batches).toHaveLength(2); }); - it('should be 1 batch if fill and line are the same', function () + it('should be 1 batch if fill and line are the same', () => { const graphics = new Graphics(); @@ -959,10 +961,10 @@ describe('Graphics', function () const geometry = graphics.geometry; geometry.updateBatches(); - expect(geometry.batches).to.have.lengthOf(1); + expect(geometry.batches).toHaveLength(1); }); - it('should not use fill if triangulation does nothing', function () + it('should not use fill if triangulation does nothing', () => { const graphics = new Graphics(); @@ -976,11 +978,11 @@ describe('Graphics', function () const geometry = graphics.geometry; geometry.updateBatches(); - expect(geometry.batches).to.have.lengthOf(2); - expect(geometry.batches[0].style.color).to.equals(0xff0000); - expect(geometry.batches[0].size).to.equal(6); - expect(geometry.batches[1].style.color).to.equals(0x00ff00); - expect(geometry.batches[1].size).to.equal(30); + expect(geometry.batches).toHaveLength(2); + expect(geometry.batches[0].style.color).toEqual(0xff0000); + expect(geometry.batches[0].size).toEqual(6); + expect(geometry.batches[1].style.color).toEqual(0x00ff00); + expect(geometry.batches[1].size).toEqual(30); }); }); }); diff --git a/packages/interaction/README.md b/packages/interaction/README.md deleted file mode 100644 index 7c9a7f362e8..00000000000 --- a/packages/interaction/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# @pixi/interaction - -## Installation - -```bash -npm install @pixi/interaction -``` - -## Usage - -```js -import { InteractionManager } from '@pixi/interaction'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('interaction', InteractionManager); -``` \ No newline at end of file diff --git a/packages/interaction/global.d.ts b/packages/interaction/global.d.ts deleted file mode 100644 index 18b4d1b7c0a..00000000000 --- a/packages/interaction/global.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare namespace GlobalMixins -{ - type InteractiveTarget = import('@pixi/interaction').InteractiveTarget; - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface DisplayObject extends InteractiveTarget - { - - } -} diff --git a/packages/interaction/package.json b/packages/interaction/package.json deleted file mode 100644 index fe6e0dcc8e3..00000000000 --- a/packages/interaction/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@pixi/interaction", - "version": "6.3.0", - "main": "dist/cjs/interaction.js", - "module": "dist/esm/interaction.js", - "bundle": "dist/browser/interaction.js", - "description": "Plugin for handling mouse, touch and pointer events", - "author": "Mat Groves", - "contributors": [ - "Matt Karl " - ], - "homepage": "http://pixijs.com/", - "bugs": "https://github.com/pixijs/pixi.js/issues", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/pixijs/pixi.js.git" - }, - "publishConfig": { - "access": "public" - }, - "files": [ - "lib", - "dist", - "*.d.ts" - ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/ticker": "6.3.0", - "@pixi/utils": "6.3.0" - } -} diff --git a/packages/interaction/src/InteractionData.ts b/packages/interaction/src/InteractionData.ts deleted file mode 100644 index eacbf953854..00000000000 --- a/packages/interaction/src/InteractionData.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { Point, IPointData } from '@pixi/math'; - -import type { DisplayObject } from '@pixi/display'; - -export type InteractivePointerEvent = PointerEvent | TouchEvent | MouseEvent; - -/** - * Holds all information related to an Interaction event - * - * @memberof PIXI - */ -export class InteractionData -{ - /** This point stores the global coords of where the touch/mouse event happened. */ - public global: Point; - - /** The target Sprite that was interacted with. */ - public target: DisplayObject; - - /** - * When passed to an event handler, this will be the original DOM Event that was captured - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent - * @see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent - * @member {MouseEvent|TouchEvent|PointerEvent} - */ - public originalEvent: InteractivePointerEvent; - - /** Unique identifier for this interaction. */ - public identifier: number; - - /** - * Indicates whether or not the pointer device that created the event is the primary pointer. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary - */ - public isPrimary: boolean; - - /** - * Indicates which button was pressed on the mouse or pointer device to trigger the event. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button - */ - public button: number; - - /** - * Indicates which buttons are pressed on the mouse or pointer device when the event is triggered. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons - */ - public buttons: number; - - /** - * The width of the pointer's contact along the x-axis, measured in CSS pixels. - * radiusX of TouchEvents will be represented by this value. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width - */ - public width: number; - - /** - * The height of the pointer's contact along the y-axis, measured in CSS pixels. - * radiusY of TouchEvents will be represented by this value. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height - */ - public height: number; - - /** - * The angle, in degrees, between the pointer device and the screen. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltX - */ - public tiltX: number; - - /** - * The angle, in degrees, between the pointer device and the screen. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/tiltY - */ - public tiltY: number; - - /** - * The type of pointer that triggered the event. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType - */ - public pointerType: string; - - /** - * Pressure applied by the pointing device during the event. A Touch's force property - * will be represented by this value. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pressure - */ - public pressure = 0; - - /** - * From TouchEvents (not PointerEvents triggered by touches), the rotationAngle of the Touch. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/Touch/rotationAngle - */ - public rotationAngle = 0; - - /** - * Twist of a stylus pointer. - * - * @see https://w3c.github.io/pointerevents/#pointerevent-interface - */ - public twist = 0; - - /** - * Barrel pressure on a stylus pointer. - * - * @see https://w3c.github.io/pointerevents/#pointerevent-interface - */ - public tangentialPressure = 0; - - constructor() - { - this.global = new Point(); - this.target = null; - this.originalEvent = null; - this.identifier = null; - this.isPrimary = false; - this.button = 0; - this.buttons = 0; - this.width = 0; - this.height = 0; - this.tiltX = 0; - this.tiltY = 0; - this.pointerType = null; - this.pressure = 0; - this.rotationAngle = 0; - this.twist = 0; - this.tangentialPressure = 0; - } - - /** - * The unique identifier of the pointer. It will be the same as `identifier`. - * - * @readonly - * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerId - */ - get pointerId(): number - { - return this.identifier; - } - - /** - * This will return the local coordinates of the specified displayObject for this InteractionData - * - * @param displayObject - The DisplayObject that you would like the local - * coords off - * @param point - A Point object in which to store the value, optional (otherwise - * will create a new point) - * @param globalPos - A Point object containing your custom global coords, optional - * (otherwise will use the current global coords) - * @return - A point containing the coordinates of the InteractionData position relative - * to the DisplayObject - */ - public getLocalPosition

(displayObject: DisplayObject, point?: P, globalPos?: IPointData): P - { - return displayObject.worldTransform.applyInverse

(globalPos || this.global, point); - } - - /** - * Copies properties from normalized event data. - * - * @param {Touch|MouseEvent|PointerEvent} event - The normalized event data - */ - public copyEvent(event: Touch | InteractivePointerEvent): void - { - // isPrimary should only change on touchstart/pointerdown, so we don't want to overwrite - // it with "false" on later events when our shim for it on touch events might not be - // accurate - if ('isPrimary' in event && event.isPrimary) - { - this.isPrimary = true; - } - this.button = 'button' in event && event.button; - // event.buttons is not available in all browsers (ie. Safari), but it does have a non-standard - // event.which property instead, which conveys the same information. - const buttons = 'buttons' in event && event.buttons; - - this.buttons = Number.isInteger(buttons) ? buttons : 'which' in event && event.which; - this.width = 'width' in event && event.width; - this.height = 'height' in event && event.height; - this.tiltX = 'tiltX' in event && event.tiltX; - this.tiltY = 'tiltY' in event && event.tiltY; - this.pointerType = 'pointerType' in event && event.pointerType; - this.pressure = 'pressure' in event && event.pressure; - this.rotationAngle = 'rotationAngle' in event && event.rotationAngle; - this.twist = ('twist' in event && event.twist) || 0; - this.tangentialPressure = ('tangentialPressure' in event && event.tangentialPressure) || 0; - } - - /** Resets the data for pooling. */ - public reset(): void - { - // isPrimary is the only property that we really need to reset - everything else is - // guaranteed to be overwritten - this.isPrimary = false; - } -} diff --git a/packages/interaction/src/InteractionEvent.ts b/packages/interaction/src/InteractionEvent.ts deleted file mode 100644 index 6b2df88ed1f..00000000000 --- a/packages/interaction/src/InteractionEvent.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { DisplayObject } from '@pixi/display'; -import type { InteractionData } from './InteractionData'; - -export type InteractionCallback = (interactionEvent: InteractionEvent, displayObject: DisplayObject, hit?: boolean) => void; - -/** - * Event class that mimics native DOM events. - * - * @memberof PIXI - */ -export class InteractionEvent -{ - /** - * Whether this event will continue propagating in the tree. - * - * Remaining events for the {@link stopsPropagatingAt} object - * will still be dispatched. - */ - public stopped: boolean; - - /** - * At which object this event stops propagating. - * - * @private - */ - public stopsPropagatingAt: DisplayObject; - - /** - * Whether we already reached the element we want to - * stop propagating at. This is important for delayed events, - * where we start over deeper in the tree again. - * - * @private - */ - public stopPropagationHint: boolean; - - /** - * The object which caused this event to be dispatched. - * For listener callback see {@link PIXI.InteractionEvent.currentTarget}. - */ - public target: DisplayObject; - - /** The object whose event listener’s callback is currently being invoked. */ - public currentTarget: DisplayObject; - - /** Type of the event. */ - public type: string; - - /** {@link InteractionData} related to this event */ - public data: InteractionData; - - constructor() - { - this.stopped = false; - this.stopsPropagatingAt = null; - this.stopPropagationHint = false; - this.target = null; - this.currentTarget = null; - this.type = null; - this.data = null; - } - - /** Prevents event from reaching any objects other than the current object. */ - public stopPropagation(): void - { - this.stopped = true; - this.stopPropagationHint = true; - this.stopsPropagatingAt = this.currentTarget; - } - - /** Resets the event. */ - public reset(): void - { - this.stopped = false; - this.stopsPropagatingAt = null; - this.stopPropagationHint = false; - this.currentTarget = null; - this.target = null; - } -} diff --git a/packages/interaction/src/InteractionManager.ts b/packages/interaction/src/InteractionManager.ts deleted file mode 100644 index 8cbaba67eb4..00000000000 --- a/packages/interaction/src/InteractionManager.ts +++ /dev/null @@ -1,1920 +0,0 @@ -import { Ticker, UPDATE_PRIORITY } from '@pixi/ticker'; -import { DisplayObject, TemporaryDisplayObject } from '@pixi/display'; -import { InteractionData, InteractivePointerEvent } from './InteractionData'; -import { InteractionEvent, InteractionCallback } from './InteractionEvent'; -import { InteractionTrackingData } from './InteractionTrackingData'; -import { TreeSearch } from './TreeSearch'; -import { EventEmitter } from '@pixi/utils'; -import { interactiveTarget } from './interactiveTarget'; - -import type { AbstractRenderer } from '@pixi/core'; -import type { Point, IPointData } from '@pixi/math'; -import type { Dict } from '@pixi/utils'; - -// Mix interactiveTarget into DisplayObject.prototype -DisplayObject.mixin(interactiveTarget); - -const MOUSE_POINTER_ID = 1; - -// Mock interface for hitTestEvent - only used inside hitTest() -interface TestInteractionEvent -{ - target: DisplayObject; - data: {global: Point}; -} - -// helpers for hitTest() - only used inside hitTest() -const hitTestEvent: TestInteractionEvent = { - target: null, - data: { - global: null, - }, -}; - -export interface InteractionManagerOptions { - autoPreventDefault?: boolean; - interactionFrequency?: number; - useSystemTicker?: boolean; -} - -export interface DelayedEvent { - displayObject: DisplayObject; - eventString: string; - eventData: InteractionEvent; -} - -interface CrossCSSStyleDeclaration extends CSSStyleDeclaration -{ - msContentZooming: string; - msTouchAction: string; -} - -/** - * The interaction manager deals with mouse, touch and pointer events. - * - * Any DisplayObject can be interactive if its `interactive` property is set to true. - * - * This manager also supports multitouch. - * - * An instance of this class is automatically created by default, and can be found at `renderer.plugins.interaction` - * - * @memberof PIXI - */ -export class InteractionManager extends EventEmitter -{ - /** - * Actively tracked InteractionData - * - * @private - * @member {Object.} - */ - public readonly activeInteractionData: { [key: number]: InteractionData }; - - /** - * Does the device support touch events - * https://www.w3.org/TR/touch-events/ - */ - public readonly supportsTouchEvents: boolean; - - /** - * Does the device support pointer events - * https://www.w3.org/Submission/pointer-events/ - */ - public readonly supportsPointerEvents: boolean; - - /** - * Pool of unused InteractionData - * - * @private - */ - public interactionDataPool: InteractionData[]; - - /** - * Internal cached let. - * - * @private - */ - public cursor: string; - - /** - * Delayed pointer events. Used to guarantee correct ordering of over/out events. - * - * @private - */ - public delayedEvents: DelayedEvent[]; - - /** - * TreeSearch component that is used to hitTest stage tree. - * - * @private - */ - public search: TreeSearch; - - /** The renderer this interaction manager works for. */ - public renderer: AbstractRenderer; - - /** - * Should default browser actions automatically be prevented. - * Does not apply to pointer events for backwards compatibility - * preventDefault on pointer events stops mouse events from firing - * Thus, for every pointer event, there will always be either a mouse of touch event alongside it. - * - * @default true - */ - public autoPreventDefault: boolean; - - /** - * Maximum frequency in milliseconds at which pointer over/out states will be checked by {@link tickerUpdate}. - * - * @default 10 - */ - public interactionFrequency: number; - - /** The mouse data. */ - public mouse: InteractionData; - - /** An event data object to handle all the event tracking/dispatching. */ - public eventData: InteractionEvent; - - /** - * This property determines if mousemove and touchmove events are fired only when the cursor - * is over the object. - * Setting to true will make things work more in line with how the DOM version works. - * Setting to false can make things easier for things like dragging - * It is currently set to false as this is how PixiJS used to work. This will be set to true in - * future versions of pixi. - * - * @default false - */ - public moveWhenInside: boolean; - - /** - * Dictionary of how different cursor modes are handled. Strings are handled as CSS cursor - * values, objects are handled as dictionaries of CSS values for interactionDOMElement, - * and functions are called instead of changing the CSS. - * Default CSS cursor values are provided for 'default' and 'pointer' modes. - * - * @member {Object.} - */ - public cursorStyles: Dict void) | CSSStyleDeclaration>; - - /** - * The mode of the cursor that is being used. - * The value of this is a key from the cursorStyles dictionary. - */ - public currentCursorMode: string; - - /** - * The current resolution / device pixel ratio. - * - * @default 1 - */ - public resolution: number; - - /** The DOM element to bind to. */ - protected interactionDOMElement: HTMLElement; - - /** Have events been attached to the dom element? */ - protected eventsAdded: boolean; - - /** Has the system ticker been added? */ - protected tickerAdded: boolean; - - /** Is the mouse hovering over the renderer? If working in worker mouse considered to be over renderer by default. */ - protected mouseOverRenderer: boolean; - - private _useSystemTicker: boolean; - private _deltaTime: number; - private _didMove: boolean; - - /** Used as a last rendered object in case renderer doesnt have _lastObjectRendered. */ - private _tempDisplayObject: DisplayObject; - - /** - * An options object specifies characteristics about the event listener. - * - * @member {Object.} - */ - private readonly _eventListenerOptions: { capture: true, passive: false }; - - /** - * @param {PIXI.CanvasRenderer|PIXI.Renderer} renderer - A reference to the current renderer - * @param options - The options for the manager. - * @param {boolean} [options.autoPreventDefault=true] - Should the manager automatically prevent default browser actions. - * @param {number} [options.interactionFrequency=10] - Maximum frequency (ms) at pointer over/out states will be checked. - * @param {number} [options.useSystemTicker=true] - Whether to add {@link tickerUpdate} to {@link PIXI.Ticker.system}. - */ - constructor(renderer: AbstractRenderer, options?: InteractionManagerOptions) - { - super(); - - options = options || {}; - - this.renderer = renderer; - this.autoPreventDefault = options.autoPreventDefault !== undefined ? options.autoPreventDefault : true; - this.interactionFrequency = options.interactionFrequency || 10; - this.mouse = new InteractionData(); - this.mouse.identifier = MOUSE_POINTER_ID; - - // setting the mouse to start off far off screen will mean that mouse over does - // not get called before we even move the mouse. - this.mouse.global.set(-999999); - - this.activeInteractionData = {}; - this.activeInteractionData[MOUSE_POINTER_ID] = this.mouse; - this.interactionDataPool = []; - this.eventData = new InteractionEvent(); - this.interactionDOMElement = null; - - this.moveWhenInside = false; - this.eventsAdded = false; - this.tickerAdded = false; - this.mouseOverRenderer = !('PointerEvent' in globalThis); - this.supportsTouchEvents = 'ontouchstart' in globalThis; - this.supportsPointerEvents = !!globalThis.PointerEvent; - - // this will make it so that you don't have to call bind all the time - - this.onPointerUp = this.onPointerUp.bind(this); - this.processPointerUp = this.processPointerUp.bind(this); - - this.onPointerCancel = this.onPointerCancel.bind(this); - this.processPointerCancel = this.processPointerCancel.bind(this); - - this.onPointerDown = this.onPointerDown.bind(this); - this.processPointerDown = this.processPointerDown.bind(this); - - this.onPointerMove = this.onPointerMove.bind(this); - this.processPointerMove = this.processPointerMove.bind(this); - - this.onPointerOut = this.onPointerOut.bind(this); - this.processPointerOverOut = this.processPointerOverOut.bind(this); - - this.onPointerOver = this.onPointerOver.bind(this); - - this.cursorStyles = { - default: 'inherit', - pointer: 'pointer', - }; - this.currentCursorMode = null; - this.cursor = null; - - this.resolution = 1; - this.delayedEvents = []; - this.search = new TreeSearch(); - - this._tempDisplayObject = new TemporaryDisplayObject(); - this._eventListenerOptions = { capture: true, passive: false }; - - /** - * Fired when a pointer device button (usually a mouse left-button) is pressed on the display - * object. - * - * @event PIXI.InteractionManager#mousedown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is pressed - * on the display object. - * - * @event PIXI.InteractionManager#rightdown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is released over the display - * object. - * - * @event PIXI.InteractionManager#mouseup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is released - * over the display object. - * - * @event PIXI.InteractionManager#rightup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is pressed and released on - * the display object. - * - * @event PIXI.InteractionManager#click - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is pressed - * and released on the display object. - * - * @event PIXI.InteractionManager#rightclick - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is released outside the - * display object that initially registered a - * [mousedown]{@link PIXI.InteractionManager#event:mousedown}. - * - * @event PIXI.InteractionManager#mouseupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is released - * outside the display object that initially registered a - * [rightdown]{@link PIXI.InteractionManager#event:rightdown}. - * - * @event PIXI.InteractionManager#rightupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved while over the display object - * - * @event PIXI.InteractionManager#mousemove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved onto the display object - * - * @event PIXI.InteractionManager#mouseover - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved off the display object - * - * @event PIXI.InteractionManager#mouseout - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is pressed on the display object. - * - * @event PIXI.InteractionManager#pointerdown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is released over the display object. - * Not always fired when some buttons are held down while others are released. In those cases, - * use [mousedown]{@link PIXI.InteractionManager#event:mousedown} and - * [mouseup]{@link PIXI.InteractionManager#event:mouseup} instead. - * - * @event PIXI.InteractionManager#pointerup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when the operating system cancels a pointer event - * - * @event PIXI.InteractionManager#pointercancel - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is pressed and released on the display object. - * - * @event PIXI.InteractionManager#pointertap - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is released outside the display object that initially - * registered a [pointerdown]{@link PIXI.InteractionManager#event:pointerdown}. - * - * @event PIXI.InteractionManager#pointerupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved while over the display object - * - * @event PIXI.InteractionManager#pointermove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved onto the display object - * - * @event PIXI.InteractionManager#pointerover - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved off the display object - * - * @event PIXI.InteractionManager#pointerout - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is placed on the display object. - * - * @event PIXI.InteractionManager#touchstart - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is removed from the display object. - * - * @event PIXI.InteractionManager#touchend - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when the operating system cancels a touch - * - * @event PIXI.InteractionManager#touchcancel - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is placed and removed from the display object. - * - * @event PIXI.InteractionManager#tap - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is removed outside of the display object that initially - * registered a [touchstart]{@link PIXI.InteractionManager#event:touchstart}. - * - * @event PIXI.InteractionManager#touchendoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is moved along the display object. - * - * @event PIXI.InteractionManager#touchmove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is pressed on the display. - * object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mousedown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is pressed - * on the display object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#rightdown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is released over the display - * object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mouseup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is released - * over the display object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#rightup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is pressed and released on - * the display object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#click - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is pressed - * and released on the display object. DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#rightclick - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button (usually a mouse left-button) is released outside the - * display object that initially registered a - * [mousedown]{@link PIXI.DisplayObject#event:mousedown}. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mouseupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device secondary button (usually a mouse right-button) is released - * outside the display object that initially registered a - * [rightdown]{@link PIXI.DisplayObject#event:rightdown}. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#rightupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved while over the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mousemove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved onto the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mouseover - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device (usually a mouse) is moved off the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#mouseout - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is pressed on the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointerdown - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is released over the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointerup - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when the operating system cancels a pointer event. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointercancel - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is pressed and released on the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointertap - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device button is released outside the display object that initially - * registered a [pointerdown]{@link PIXI.DisplayObject#event:pointerdown}. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointerupoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved while over the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointermove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved onto the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointerover - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a pointer device is moved off the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#pointerout - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is placed on the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#touchstart - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is removed from the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#touchend - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when the operating system cancels a touch. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#touchcancel - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is placed and removed from the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#tap - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is removed outside of the display object that initially - * registered a [touchstart]{@link PIXI.DisplayObject#event:touchstart}. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#touchendoutside - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - /** - * Fired when a touch point is moved along the display object. - * DisplayObject's `interactive` property must be set to `true` to fire event. - * - * This comes from the @pixi/interaction package. - * - * @event PIXI.DisplayObject#touchmove - * @param {PIXI.InteractionEvent} event - Interaction event - */ - - this._useSystemTicker = options.useSystemTicker !== undefined ? options.useSystemTicker : true; - - this.setTargetElement(this.renderer.view, this.renderer.resolution); - } - - /** - * Should the InteractionManager automatically add {@link tickerUpdate} to {@link PIXI.Ticker.system}. - * - * @default true - */ - get useSystemTicker(): boolean - { - return this._useSystemTicker; - } - set useSystemTicker(useSystemTicker: boolean) - { - this._useSystemTicker = useSystemTicker; - - if (useSystemTicker) - { - this.addTickerListener(); - } - else - { - this.removeTickerListener(); - } - } - - /** - * Last rendered object or temp object. - * - * @readonly - * @protected - */ - get lastObjectRendered(): DisplayObject - { - return (this.renderer._lastObjectRendered as DisplayObject) || this._tempDisplayObject; - } - - /** - * Hit tests a point against the display tree, returning the first interactive object that is hit. - * - * @param globalPoint - A point to hit test with, in global space. - * @param root - The root display object to start from. If omitted, defaults - * to the last rendered root of the associated renderer. - * @return - The hit display object, if any. - */ - public hitTest(globalPoint: Point, root?: DisplayObject): DisplayObject - { - // clear the target for our hit test - hitTestEvent.target = null; - // assign the global point - hitTestEvent.data.global = globalPoint; - // ensure safety of the root - if (!root) - { - root = this.lastObjectRendered; - } - // run the hit test - this.processInteractive(hitTestEvent as InteractionEvent, root, null, true); - // return our found object - it'll be null if we didn't hit anything - - return hitTestEvent.target; - } - - /** - * Sets the DOM element which will receive mouse/touch events. This is useful for when you have - * other DOM elements on top of the renderers Canvas element. With this you'll be bale to delegate - * another DOM element to receive those events. - * - * @param element - the DOM element which will receive mouse and touch events. - * @param resolution - The resolution / device pixel ratio of the new element (relative to the canvas). - */ - public setTargetElement(element: HTMLElement, resolution = 1): void - { - this.removeTickerListener(); - - this.removeEvents(); - - this.interactionDOMElement = element; - - this.resolution = resolution; - - this.addEvents(); - - this.addTickerListener(); - } - - /** Adds the ticker listener. */ - private addTickerListener(): void - { - if (this.tickerAdded || !this.interactionDOMElement || !this._useSystemTicker) - { - return; - } - - Ticker.system.add(this.tickerUpdate, this, UPDATE_PRIORITY.INTERACTION); - - this.tickerAdded = true; - } - - /** Removes the ticker listener. */ - private removeTickerListener(): void - { - if (!this.tickerAdded) - { - return; - } - - Ticker.system.remove(this.tickerUpdate, this); - - this.tickerAdded = false; - } - - /** Registers all the DOM events. */ - private addEvents(): void - { - if (this.eventsAdded || !this.interactionDOMElement) - { - return; - } - - const style = this.interactionDOMElement.style as CrossCSSStyleDeclaration; - - if (globalThis.navigator.msPointerEnabled) - { - style.msContentZooming = 'none'; - style.msTouchAction = 'none'; - } - else if (this.supportsPointerEvents) - { - style.touchAction = 'none'; - } - - /* - * These events are added first, so that if pointer events are normalized, they are fired - * in the same order as non-normalized events. ie. pointer event 1st, mouse / touch 2nd - */ - if (this.supportsPointerEvents) - { - globalThis.document.addEventListener('pointermove', this.onPointerMove, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('pointerdown', this.onPointerDown, this._eventListenerOptions); - // pointerout is fired in addition to pointerup (for touch events) and pointercancel - // we already handle those, so for the purposes of what we do in onPointerOut, we only - // care about the pointerleave event - this.interactionDOMElement.addEventListener('pointerleave', this.onPointerOut, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('pointerover', this.onPointerOver, this._eventListenerOptions); - globalThis.addEventListener('pointercancel', this.onPointerCancel, this._eventListenerOptions); - globalThis.addEventListener('pointerup', this.onPointerUp, this._eventListenerOptions); - } - else - { - globalThis.document.addEventListener('mousemove', this.onPointerMove, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('mousedown', this.onPointerDown, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('mouseout', this.onPointerOut, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('mouseover', this.onPointerOver, this._eventListenerOptions); - globalThis.addEventListener('mouseup', this.onPointerUp, this._eventListenerOptions); - } - - // always look directly for touch events so that we can provide original data - // In a future version we should change this to being just a fallback and rely solely on - // PointerEvents whenever available - if (this.supportsTouchEvents) - { - this.interactionDOMElement.addEventListener('touchstart', this.onPointerDown, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('touchcancel', this.onPointerCancel, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('touchend', this.onPointerUp, this._eventListenerOptions); - this.interactionDOMElement.addEventListener('touchmove', this.onPointerMove, this._eventListenerOptions); - } - - this.eventsAdded = true; - } - - /** Removes all the DOM events that were previously registered. */ - private removeEvents(): void - { - if (!this.eventsAdded || !this.interactionDOMElement) - { - return; - } - - const style = this.interactionDOMElement.style as CrossCSSStyleDeclaration; - - if (globalThis.navigator.msPointerEnabled) - { - style.msContentZooming = ''; - style.msTouchAction = ''; - } - else if (this.supportsPointerEvents) - { - style.touchAction = ''; - } - - if (this.supportsPointerEvents) - { - globalThis.document.removeEventListener('pointermove', this.onPointerMove, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('pointerdown', this.onPointerDown, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('pointerleave', this.onPointerOut, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('pointerover', this.onPointerOver, this._eventListenerOptions); - globalThis.removeEventListener('pointercancel', this.onPointerCancel, this._eventListenerOptions); - globalThis.removeEventListener('pointerup', this.onPointerUp, this._eventListenerOptions); - } - else - { - globalThis.document.removeEventListener('mousemove', this.onPointerMove, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('mousedown', this.onPointerDown, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('mouseout', this.onPointerOut, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('mouseover', this.onPointerOver, this._eventListenerOptions); - globalThis.removeEventListener('mouseup', this.onPointerUp, this._eventListenerOptions); - } - - if (this.supportsTouchEvents) - { - this.interactionDOMElement.removeEventListener('touchstart', this.onPointerDown, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('touchcancel', this.onPointerCancel, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('touchend', this.onPointerUp, this._eventListenerOptions); - this.interactionDOMElement.removeEventListener('touchmove', this.onPointerMove, this._eventListenerOptions); - } - - this.interactionDOMElement = null; - - this.eventsAdded = false; - } - - /** - * Updates the state of interactive objects if at least {@link interactionFrequency} - * milliseconds have passed since the last invocation. - * - * Invoked by a throttled ticker update from {@link PIXI.Ticker.system}. - * - * @param deltaTime - time delta since the last call - */ - public tickerUpdate(deltaTime: number): void - { - this._deltaTime += deltaTime; - - if (this._deltaTime < this.interactionFrequency) - { - return; - } - - this._deltaTime = 0; - - this.update(); - } - - /** Updates the state of interactive objects. */ - public update(): void - { - if (!this.interactionDOMElement) - { - return; - } - - // if the user move the mouse this check has already been done using the mouse move! - if (this._didMove) - { - this._didMove = false; - - return; - } - - this.cursor = null; - - // Resets the flag as set by a stopPropagation call. This flag is usually reset by a user interaction of any kind, - // but there was a scenario of a display object moving under a static mouse cursor. - // In this case, mouseover and mouseevents would not pass the flag test in dispatchEvent function - for (const k in this.activeInteractionData) - { - // eslint-disable-next-line no-prototype-builtins - if (this.activeInteractionData.hasOwnProperty(k)) - { - const interactionData = this.activeInteractionData[k]; - - if (interactionData.originalEvent && interactionData.pointerType !== 'touch') - { - const interactionEvent = this.configureInteractionEventForDOMEvent( - this.eventData, - interactionData.originalEvent as PointerEvent, - interactionData - ); - - this.processInteractive( - interactionEvent, - this.lastObjectRendered, - this.processPointerOverOut, - true - ); - } - } - } - - this.setCursorMode(this.cursor); - } - - /** - * Sets the current cursor mode, handling any callbacks or CSS style changes. - * - * @param mode - cursor mode, a key from the cursorStyles dictionary - */ - public setCursorMode(mode: string): void - { - mode = mode || 'default'; - let applyStyles = true; - - // offscreen canvas does not support setting styles, but cursor modes can be functions, - // in order to handle pixi rendered cursors, so we can't bail - if (globalThis.OffscreenCanvas && this.interactionDOMElement instanceof OffscreenCanvas) - { - applyStyles = false; - } - // if the mode didn't actually change, bail early - if (this.currentCursorMode === mode) - { - return; - } - this.currentCursorMode = mode; - const style = this.cursorStyles[mode]; - - // only do things if there is a cursor style for it - if (style) - { - switch (typeof style) - { - case 'string': - // string styles are handled as cursor CSS - if (applyStyles) - { - this.interactionDOMElement.style.cursor = style; - } - break; - case 'function': - // functions are just called, and passed the cursor mode - style(mode); - break; - case 'object': - // if it is an object, assume that it is a dictionary of CSS styles, - // apply it to the interactionDOMElement - if (applyStyles) - { - Object.assign(this.interactionDOMElement.style, style); - } - break; - } - } - else if (applyStyles && typeof mode === 'string' && !Object.prototype.hasOwnProperty.call(this.cursorStyles, mode)) - { - // if it mode is a string (not a Symbol) and cursorStyles doesn't have any entry - // for the mode, then assume that the dev wants it to be CSS for the cursor. - this.interactionDOMElement.style.cursor = mode; - } - } - - /** - * Dispatches an event on the display object that was interacted with. - * - * @param displayObject - the display object in question - * @param eventString - the name of the event (e.g, mousedown) - * @param eventData - the event data object - */ - private dispatchEvent(displayObject: DisplayObject, eventString: string, eventData: InteractionEvent): void - { - // Even if the event was stopped, at least dispatch any remaining events - // for the same display object. - if (!eventData.stopPropagationHint || displayObject === eventData.stopsPropagatingAt) - { - eventData.currentTarget = displayObject; - eventData.type = eventString; - - displayObject.emit(eventString, eventData); - - if ((displayObject as any)[eventString]) - { - (displayObject as any)[eventString](eventData); - } - } - } - - /** - * Puts a event on a queue to be dispatched later. This is used to guarantee correct - * ordering of over/out events. - * - * @param displayObject - the display object in question - * @param eventString - the name of the event (e.g, mousedown) - * @param eventData - the event data object - */ - private delayDispatchEvent(displayObject: DisplayObject, eventString: string, eventData: InteractionEvent): void - { - this.delayedEvents.push({ displayObject, eventString, eventData }); - } - - /** - * Maps x and y coords from a DOM object and maps them correctly to the PixiJS view. The - * resulting value is stored in the point. This takes into account the fact that the DOM - * element could be scaled and positioned anywhere on the screen. - * - * @param point - the point that the result will be stored in - * @param x - the x coord of the position to map - * @param y - the y coord of the position to map - */ - public mapPositionToPoint(point: IPointData, x: number, y: number): void - { - let rect; - - // IE 11 fix - if (!this.interactionDOMElement.parentElement) - { - rect = { - x: 0, - y: 0, - width: (this.interactionDOMElement as any).width, - height: (this.interactionDOMElement as any).height, - left: 0, - top: 0 - }; - } - else - { - rect = this.interactionDOMElement.getBoundingClientRect(); - } - - const resolutionMultiplier = 1.0 / this.resolution; - - point.x = ((x - rect.left) * ((this.interactionDOMElement as any).width / rect.width)) * resolutionMultiplier; - point.y = ((y - rect.top) * ((this.interactionDOMElement as any).height / rect.height)) * resolutionMultiplier; - } - - /** - * This function is provides a neat way of crawling through the scene graph and running a - * specified function on all interactive objects it finds. It will also take care of hit - * testing the interactive objects and passes the hit across in the function. - * - * @protected - * @param interactionEvent - event containing the point that - * is tested for collision - * @param displayObject - the displayObject - * that will be hit test (recursively crawls its children) - * @param func - the function that will be called on each interactive object. The - * interactionEvent, displayObject and hit will be passed to the function - * @param hitTest - indicates whether we want to calculate hits - * or just iterate through all interactive objects - */ - public processInteractive(interactionEvent: InteractionEvent, displayObject: DisplayObject, - func?: InteractionCallback, hitTest?: boolean - ): void - { - const hit = this.search.findHit(interactionEvent, displayObject, func, hitTest); - - const delayedEvents = this.delayedEvents; - - if (!delayedEvents.length) - { - return hit; - } - // Reset the propagation hint, because we start deeper in the tree again. - interactionEvent.stopPropagationHint = false; - - const delayedLen = delayedEvents.length; - - this.delayedEvents = []; - - for (let i = 0; i < delayedLen; i++) - { - const { displayObject, eventString, eventData } = delayedEvents[i]; - - // When we reach the object we wanted to stop propagating at, - // set the propagation hint. - if (eventData.stopsPropagatingAt === displayObject) - { - eventData.stopPropagationHint = true; - } - - this.dispatchEvent(displayObject, eventString, eventData); - } - - return hit; - } - - /** - * Is called when the pointer button is pressed down on the renderer element - * - * @param originalEvent - The DOM event of a pointer button being pressed down - */ - private onPointerDown(originalEvent: InteractivePointerEvent): void - { - // if we support touch events, then only use those for touch events, not pointer events - if (this.supportsTouchEvents && (originalEvent as PointerEvent).pointerType === 'touch') return; - - const events = this.normalizeToPointerData(originalEvent); - - /* - * No need to prevent default on natural pointer events, as there are no side effects - * Normalized events, however, may have the double mousedown/touchstart issue on the native android browser, - * so still need to be prevented. - */ - - // Guaranteed that there will be at least one event in events, and all events must have the same pointer type - - if (this.autoPreventDefault && (events[0] as any).isNormalized) - { - const cancelable = originalEvent.cancelable || !('cancelable' in originalEvent); - - if (cancelable) - { - originalEvent.preventDefault(); - } - } - - const eventLen = events.length; - - for (let i = 0; i < eventLen; i++) - { - const event = events[i]; - - const interactionData = this.getInteractionDataForPointerId(event); - - const interactionEvent = this.configureInteractionEventForDOMEvent(this.eventData, event, interactionData); - - interactionEvent.data.originalEvent = originalEvent; - - this.processInteractive(interactionEvent, this.lastObjectRendered, this.processPointerDown, true); - - this.emit('pointerdown', interactionEvent); - if (event.pointerType === 'touch') - { - this.emit('touchstart', interactionEvent); - } - // emit a mouse event for "pen" pointers, the way a browser would emit a fallback event - else if (event.pointerType === 'mouse' || event.pointerType === 'pen') - { - const isRightButton = event.button === 2; - - this.emit(isRightButton ? 'rightdown' : 'mousedown', this.eventData); - } - } - } - - /** - * Processes the result of the pointer down check and dispatches the event if need be - * - * @param interactionEvent - The interaction event wrapping the DOM event - * @param displayObject - The display object that was tested - * @param hit - the result of the hit test on the display object - */ - private processPointerDown(interactionEvent: InteractionEvent, displayObject: DisplayObject, hit: boolean): void - { - const data = interactionEvent.data; - const id = interactionEvent.data.identifier; - - if (hit) - { - if (!displayObject.trackedPointers[id]) - { - displayObject.trackedPointers[id] = new InteractionTrackingData(id); - } - this.dispatchEvent(displayObject, 'pointerdown', interactionEvent); - - if (data.pointerType === 'touch') - { - this.dispatchEvent(displayObject, 'touchstart', interactionEvent); - } - else if (data.pointerType === 'mouse' || data.pointerType === 'pen') - { - const isRightButton = data.button === 2; - - if (isRightButton) - { - displayObject.trackedPointers[id].rightDown = true; - } - else - { - displayObject.trackedPointers[id].leftDown = true; - } - - this.dispatchEvent(displayObject, isRightButton ? 'rightdown' : 'mousedown', interactionEvent); - } - } - } - - /** - * Is called when the pointer button is released on the renderer element - * - * @param originalEvent - The DOM event of a pointer button being released - * @param cancelled - true if the pointer is cancelled - * @param func - Function passed to {@link processInteractive} - */ - private onPointerComplete(originalEvent: InteractivePointerEvent, cancelled: boolean, func: InteractionCallback): void - { - const events = this.normalizeToPointerData(originalEvent); - - const eventLen = events.length; - - // if the event wasn't targeting our canvas, then consider it to be pointerupoutside - // in all cases (unless it was a pointercancel) - const eventAppend = originalEvent.target !== this.interactionDOMElement ? 'outside' : ''; - - for (let i = 0; i < eventLen; i++) - { - const event = events[i]; - - const interactionData = this.getInteractionDataForPointerId(event); - - const interactionEvent = this.configureInteractionEventForDOMEvent(this.eventData, event, interactionData); - - interactionEvent.data.originalEvent = originalEvent; - - // perform hit testing for events targeting our canvas or cancel events - this.processInteractive(interactionEvent, this.lastObjectRendered, func, cancelled || !eventAppend); - - this.emit(cancelled ? 'pointercancel' : `pointerup${eventAppend}`, interactionEvent); - - if (event.pointerType === 'mouse' || event.pointerType === 'pen') - { - const isRightButton = event.button === 2; - - this.emit(isRightButton ? `rightup${eventAppend}` : `mouseup${eventAppend}`, interactionEvent); - } - else if (event.pointerType === 'touch') - { - this.emit(cancelled ? 'touchcancel' : `touchend${eventAppend}`, interactionEvent); - this.releaseInteractionDataForPointerId(event.pointerId); - } - } - } - - /** - * Is called when the pointer button is cancelled - * - * @param event - The DOM event of a pointer button being released - */ - private onPointerCancel(event: InteractivePointerEvent): void - { - // if we support touch events, then only use those for touch events, not pointer events - if (this.supportsTouchEvents && (event as PointerEvent).pointerType === 'touch') return; - - this.onPointerComplete(event, true, this.processPointerCancel); - } - - /** - * Processes the result of the pointer cancel check and dispatches the event if need be - * - * @param interactionEvent - The interaction event wrapping the DOM event - * @param displayObject - The display object that was tested - */ - private processPointerCancel(interactionEvent: InteractionEvent, displayObject: DisplayObject): void - { - const data = interactionEvent.data; - - const id = interactionEvent.data.identifier; - - if (displayObject.trackedPointers[id] !== undefined) - { - delete displayObject.trackedPointers[id]; - this.dispatchEvent(displayObject, 'pointercancel', interactionEvent); - - if (data.pointerType === 'touch') - { - this.dispatchEvent(displayObject, 'touchcancel', interactionEvent); - } - } - } - - /** - * Is called when the pointer button is released on the renderer element - * - * @param event - The DOM event of a pointer button being released - */ - private onPointerUp(event: InteractivePointerEvent): void - { - // if we support touch events, then only use those for touch events, not pointer events - if (this.supportsTouchEvents && (event as PointerEvent).pointerType === 'touch') return; - - this.onPointerComplete(event, false, this.processPointerUp); - } - - /** - * Processes the result of the pointer up check and dispatches the event if need be - * - * @param interactionEvent - The interaction event wrapping the DOM event - * @param displayObject - The display object that was tested - * @param hit - the result of the hit test on the display object - */ - private processPointerUp(interactionEvent: InteractionEvent, displayObject: DisplayObject, hit: boolean): void - { - const data = interactionEvent.data; - - const id = interactionEvent.data.identifier; - - const trackingData = displayObject.trackedPointers[id]; - - const isTouch = data.pointerType === 'touch'; - - const isMouse = (data.pointerType === 'mouse' || data.pointerType === 'pen'); - // need to track mouse down status in the mouse block so that we can emit - // event in a later block - let isMouseTap = false; - - // Mouse only - if (isMouse) - { - const isRightButton = data.button === 2; - - const flags = InteractionTrackingData.FLAGS; - - const test = isRightButton ? flags.RIGHT_DOWN : flags.LEFT_DOWN; - - const isDown = trackingData !== undefined && (trackingData.flags & test); - - if (hit) - { - this.dispatchEvent(displayObject, isRightButton ? 'rightup' : 'mouseup', interactionEvent); - - if (isDown) - { - this.dispatchEvent(displayObject, isRightButton ? 'rightclick' : 'click', interactionEvent); - // because we can confirm that the mousedown happened on this object, flag for later emit of pointertap - isMouseTap = true; - } - } - else if (isDown) - { - this.dispatchEvent(displayObject, isRightButton ? 'rightupoutside' : 'mouseupoutside', interactionEvent); - } - // update the down state of the tracking data - if (trackingData) - { - if (isRightButton) - { - trackingData.rightDown = false; - } - else - { - trackingData.leftDown = false; - } - } - } - - // Pointers and Touches, and Mouse - if (hit) - { - this.dispatchEvent(displayObject, 'pointerup', interactionEvent); - if (isTouch) this.dispatchEvent(displayObject, 'touchend', interactionEvent); - - if (trackingData) - { - // emit pointertap if not a mouse, or if the mouse block decided it was a tap - if (!isMouse || isMouseTap) - { - this.dispatchEvent(displayObject, 'pointertap', interactionEvent); - } - if (isTouch) - { - this.dispatchEvent(displayObject, 'tap', interactionEvent); - // touches are no longer over (if they ever were) when we get the touchend - // so we should ensure that we don't keep pretending that they are - trackingData.over = false; - } - } - } - else if (trackingData) - { - this.dispatchEvent(displayObject, 'pointerupoutside', interactionEvent); - if (isTouch) this.dispatchEvent(displayObject, 'touchendoutside', interactionEvent); - } - // Only remove the tracking data if there is no over/down state still associated with it - if (trackingData && trackingData.none) - { - delete displayObject.trackedPointers[id]; - } - } - - /** - * Is called when the pointer moves across the renderer element - * - * @param originalEvent - The DOM event of a pointer moving - */ - private onPointerMove(originalEvent: InteractivePointerEvent): void - { - // if we support touch events, then only use those for touch events, not pointer events - if (this.supportsTouchEvents && (originalEvent as PointerEvent).pointerType === 'touch') return; - - const events = this.normalizeToPointerData(originalEvent); - - if (events[0].pointerType === 'mouse' || events[0].pointerType === 'pen') - { - this._didMove = true; - - this.cursor = null; - } - - const eventLen = events.length; - - for (let i = 0; i < eventLen; i++) - { - const event = events[i]; - - const interactionData = this.getInteractionDataForPointerId(event); - - const interactionEvent = this.configureInteractionEventForDOMEvent(this.eventData, event, interactionData); - - interactionEvent.data.originalEvent = originalEvent; - - this.processInteractive(interactionEvent, this.lastObjectRendered, this.processPointerMove, true); - - this.emit('pointermove', interactionEvent); - if (event.pointerType === 'touch') this.emit('touchmove', interactionEvent); - if (event.pointerType === 'mouse' || event.pointerType === 'pen') this.emit('mousemove', interactionEvent); - } - - if (events[0].pointerType === 'mouse') - { - this.setCursorMode(this.cursor); - - // TODO BUG for parents interactive object (border order issue) - } - } - - /** - * Processes the result of the pointer move check and dispatches the event if need be - * - * @param interactionEvent - The interaction event wrapping the DOM event - * @param displayObject - The display object that was tested - * @param hit - the result of the hit test on the display object - */ - private processPointerMove(interactionEvent: InteractionEvent, displayObject: DisplayObject, hit: boolean): void - { - const data = interactionEvent.data; - - const isTouch = data.pointerType === 'touch'; - - const isMouse = (data.pointerType === 'mouse' || data.pointerType === 'pen'); - - if (isMouse) - { - this.processPointerOverOut(interactionEvent, displayObject, hit); - } - - if (!this.moveWhenInside || hit) - { - this.dispatchEvent(displayObject, 'pointermove', interactionEvent); - if (isTouch) this.dispatchEvent(displayObject, 'touchmove', interactionEvent); - if (isMouse) this.dispatchEvent(displayObject, 'mousemove', interactionEvent); - } - } - - /** - * Is called when the pointer is moved out of the renderer element - * - * @private - * @param {PointerEvent} originalEvent - The DOM event of a pointer being moved out - */ - private onPointerOut(originalEvent: InteractivePointerEvent): void - { - // if we support touch events, then only use those for touch events, not pointer events - if (this.supportsTouchEvents && (originalEvent as PointerEvent).pointerType === 'touch') return; - - const events = this.normalizeToPointerData(originalEvent); - - // Only mouse and pointer can call onPointerOut, so events will always be length 1 - const event = events[0]; - - if (event.pointerType === 'mouse') - { - this.mouseOverRenderer = false; - this.setCursorMode(null); - } - - const interactionData = this.getInteractionDataForPointerId(event); - - const interactionEvent = this.configureInteractionEventForDOMEvent(this.eventData, event, interactionData); - - interactionEvent.data.originalEvent = event; - - this.processInteractive(interactionEvent, this.lastObjectRendered, this.processPointerOverOut, false); - - this.emit('pointerout', interactionEvent); - if (event.pointerType === 'mouse' || event.pointerType === 'pen') - { - this.emit('mouseout', interactionEvent); - } - else - { - // we can get touchleave events after touchend, so we want to make sure we don't - // introduce memory leaks - this.releaseInteractionDataForPointerId(interactionData.identifier); - } - } - - /** - * Processes the result of the pointer over/out check and dispatches the event if need be. - * - * @param interactionEvent - The interaction event wrapping the DOM event - * @param displayObject - The display object that was tested - * @param hit - the result of the hit test on the display object - */ - private processPointerOverOut(interactionEvent: InteractionEvent, displayObject: DisplayObject, hit: boolean): void - { - const data = interactionEvent.data; - - const id = interactionEvent.data.identifier; - - const isMouse = (data.pointerType === 'mouse' || data.pointerType === 'pen'); - - let trackingData = displayObject.trackedPointers[id]; - - // if we just moused over the display object, then we need to track that state - if (hit && !trackingData) - { - trackingData = displayObject.trackedPointers[id] = new InteractionTrackingData(id); - } - - if (trackingData === undefined) return; - - if (hit && this.mouseOverRenderer) - { - if (!trackingData.over) - { - trackingData.over = true; - this.delayDispatchEvent(displayObject, 'pointerover', interactionEvent); - if (isMouse) - { - this.delayDispatchEvent(displayObject, 'mouseover', interactionEvent); - } - } - - // only change the cursor if it has not already been changed (by something deeper in the - // display tree) - if (isMouse && this.cursor === null) - { - this.cursor = displayObject.cursor; - } - } - else if (trackingData.over) - { - trackingData.over = false; - this.dispatchEvent(displayObject, 'pointerout', this.eventData); - if (isMouse) - { - this.dispatchEvent(displayObject, 'mouseout', interactionEvent); - } - // if there is no mouse down information for the pointer, then it is safe to delete - if (trackingData.none) - { - delete displayObject.trackedPointers[id]; - } - } - } - - /** - * Is called when the pointer is moved into the renderer element. - * - * @param originalEvent - The DOM event of a pointer button being moved into the renderer view. - */ - private onPointerOver(originalEvent: InteractivePointerEvent): void - { - const events = this.normalizeToPointerData(originalEvent); - - // Only mouse and pointer can call onPointerOver, so events will always be length 1 - const event = events[0]; - - const interactionData = this.getInteractionDataForPointerId(event); - - const interactionEvent = this.configureInteractionEventForDOMEvent(this.eventData, event, interactionData); - - interactionEvent.data.originalEvent = event; - - if (event.pointerType === 'mouse') - { - this.mouseOverRenderer = true; - } - - this.emit('pointerover', interactionEvent); - if (event.pointerType === 'mouse' || event.pointerType === 'pen') - { - this.emit('mouseover', interactionEvent); - } - } - - /** - * Get InteractionData for a given pointerId. Store that data as well. - * - * @param event - Normalized pointer event, output from normalizeToPointerData. - * @return - Interaction data for the given pointer identifier. - */ - private getInteractionDataForPointerId(event: PointerEvent): InteractionData - { - const pointerId = event.pointerId; - - let interactionData; - - if (pointerId === MOUSE_POINTER_ID || event.pointerType === 'mouse') - { - interactionData = this.mouse; - } - else if (this.activeInteractionData[pointerId]) - { - interactionData = this.activeInteractionData[pointerId]; - } - else - { - interactionData = this.interactionDataPool.pop() || new InteractionData(); - interactionData.identifier = pointerId; - this.activeInteractionData[pointerId] = interactionData; - } - // copy properties from the event, so that we can make sure that touch/pointer specific - // data is available - interactionData.copyEvent(event); - - return interactionData; - } - - /** - * Return unused InteractionData to the pool, for a given pointerId - * - * @param pointerId - Identifier from a pointer event - */ - private releaseInteractionDataForPointerId(pointerId: number): void - { - const interactionData = this.activeInteractionData[pointerId]; - - if (interactionData) - { - delete this.activeInteractionData[pointerId]; - interactionData.reset(); - this.interactionDataPool.push(interactionData); - } - } - - /** - * Configure an InteractionEvent to wrap a DOM PointerEvent and InteractionData - * - * @param interactionEvent - The event to be configured - * @param pointerEvent - The DOM event that will be paired with the InteractionEvent - * @param interactionData - The InteractionData that will be paired - * with the InteractionEvent - * @return - the interaction event that was passed in - */ - private configureInteractionEventForDOMEvent(interactionEvent: InteractionEvent, pointerEvent: PointerEvent, - interactionData: InteractionData - ): InteractionEvent - { - interactionEvent.data = interactionData; - - this.mapPositionToPoint(interactionData.global, pointerEvent.clientX, pointerEvent.clientY); - - // Not really sure why this is happening, but it's how a previous version handled things - if (pointerEvent.pointerType === 'touch') - { - (pointerEvent as any).globalX = interactionData.global.x; - (pointerEvent as any).globalY = interactionData.global.y; - } - - interactionData.originalEvent = pointerEvent; - interactionEvent.reset(); - - return interactionEvent; - } - - /** - * Ensures that the original event object contains all data that a regular pointer event would have - * - * @param {TouchEvent|MouseEvent|PointerEvent} event - The original event data from a touch or mouse event - * @return - An array containing a single normalized pointer event, in the case of a pointer - * or mouse event, or a multiple normalized pointer events if there are multiple changed touches - */ - private normalizeToPointerData(event: InteractivePointerEvent): PointerEvent[] - { - const normalizedEvents = []; - - if (this.supportsTouchEvents && event instanceof TouchEvent) - { - for (let i = 0, li = event.changedTouches.length; i < li; i++) - { - const touch = event.changedTouches[i] as PixiTouch; - - if (typeof touch.button === 'undefined') touch.button = event.touches.length ? 1 : 0; - if (typeof touch.buttons === 'undefined') touch.buttons = event.touches.length ? 1 : 0; - if (typeof touch.isPrimary === 'undefined') - { - touch.isPrimary = event.touches.length === 1 && event.type === 'touchstart'; - } - if (typeof touch.width === 'undefined') touch.width = touch.radiusX || 1; - if (typeof touch.height === 'undefined') touch.height = touch.radiusY || 1; - if (typeof touch.tiltX === 'undefined') touch.tiltX = 0; - if (typeof touch.tiltY === 'undefined') touch.tiltY = 0; - if (typeof touch.pointerType === 'undefined') touch.pointerType = 'touch'; - if (typeof touch.pointerId === 'undefined') touch.pointerId = touch.identifier || 0; - if (typeof touch.pressure === 'undefined') touch.pressure = touch.force || 0.5; - if (typeof touch.twist === 'undefined') touch.twist = 0; - if (typeof touch.tangentialPressure === 'undefined') touch.tangentialPressure = 0; - // TODO: Remove these, as layerX/Y is not a standard, is deprecated, has uneven - // support, and the fill ins are not quite the same - // offsetX/Y might be okay, but is not the same as clientX/Y when the canvas's top - // left is not 0,0 on the page - if (typeof touch.layerX === 'undefined') touch.layerX = touch.offsetX = touch.clientX; - if (typeof touch.layerY === 'undefined') touch.layerY = touch.offsetY = touch.clientY; - - // mark the touch as normalized, just so that we know we did it - touch.isNormalized = true; - - normalizedEvents.push(touch); - } - } - // apparently PointerEvent subclasses MouseEvent, so yay - else if (!globalThis.MouseEvent - || (event instanceof MouseEvent && (!this.supportsPointerEvents || !(event instanceof globalThis.PointerEvent)))) - { - const tempEvent = event as PixiPointerEvent; - - if (typeof tempEvent.isPrimary === 'undefined') tempEvent.isPrimary = true; - if (typeof tempEvent.width === 'undefined') tempEvent.width = 1; - if (typeof tempEvent.height === 'undefined') tempEvent.height = 1; - if (typeof tempEvent.tiltX === 'undefined') tempEvent.tiltX = 0; - if (typeof tempEvent.tiltY === 'undefined') tempEvent.tiltY = 0; - if (typeof tempEvent.pointerType === 'undefined') tempEvent.pointerType = 'mouse'; - if (typeof tempEvent.pointerId === 'undefined') tempEvent.pointerId = MOUSE_POINTER_ID; - if (typeof tempEvent.pressure === 'undefined') tempEvent.pressure = 0.5; - if (typeof tempEvent.twist === 'undefined') tempEvent.twist = 0; - if (typeof tempEvent.tangentialPressure === 'undefined') tempEvent.tangentialPressure = 0; - - // mark the mouse event as normalized, just so that we know we did it - tempEvent.isNormalized = true; - - normalizedEvents.push(tempEvent); - } - else - { - normalizedEvents.push(event); - } - - return normalizedEvents as PointerEvent[]; - } - - /** Destroys the interaction manager. */ - public destroy(): void - { - this.removeEvents(); - - this.removeTickerListener(); - - this.removeAllListeners(); - - this.renderer = null; - - this.mouse = null; - - this.eventData = null; - - this.interactionDOMElement = null; - - this.onPointerDown = null; - this.processPointerDown = null; - - this.onPointerUp = null; - this.processPointerUp = null; - - this.onPointerCancel = null; - this.processPointerCancel = null; - - this.onPointerMove = null; - this.processPointerMove = null; - - this.onPointerOut = null; - this.processPointerOverOut = null; - - this.onPointerOver = null; - - this.search = null; - } -} - -interface PixiPointerEvent extends PointerEvent -{ - isPrimary: boolean; - width: number; - height: number; - tiltX: number; - tiltY: number; - pointerType: string; - pointerId: number; - pressure: number; - twist: number; - tangentialPressure: number; - isNormalized: boolean; -} - -interface PixiTouch extends Touch -{ - button: number; - buttons: number; - isPrimary: boolean; - width: number; - height: number; - tiltX: number; - tiltY: number; - pointerType: string; - pointerId: number; - pressure: number; - twist: number; - tangentialPressure: number; - layerX: number; - layerY: number; - offsetX: number; - offsetY: number; - isNormalized: boolean; -} diff --git a/packages/interaction/src/InteractionTrackingData.ts b/packages/interaction/src/InteractionTrackingData.ts deleted file mode 100644 index 1f6c32ce499..00000000000 --- a/packages/interaction/src/InteractionTrackingData.ts +++ /dev/null @@ -1,142 +0,0 @@ -export interface InteractionTrackingFlags -{ - OVER: number; - LEFT_DOWN: number; - RIGHT_DOWN: number; - NONE: number; -} - -/** - * DisplayObjects with the {@link PIXI.interactiveTarget} mixin use this class to track interactions - * - * @class - * @private - * @memberof PIXI - */ -export class InteractionTrackingData -{ - public static FLAGS: Readonly = Object.freeze({ - NONE: 0, - OVER: 1 << 0, - LEFT_DOWN: 1 << 1, - RIGHT_DOWN: 1 << 2, - }); - - private readonly _pointerId: number; - private _flags: number; - - /** - * @param {number} pointerId - Unique pointer id of the event - * @private - */ - constructor(pointerId: number) - { - this._pointerId = pointerId; - this._flags = InteractionTrackingData.FLAGS.NONE; - } - - /** - * - * @private - * @param {number} flag - The interaction flag to set - * @param {boolean} yn - Should the flag be set or unset - */ - private _doSet(flag: number, yn: boolean): void - { - if (yn) - { - this._flags = this._flags | flag; - } - else - { - this._flags = this._flags & (~flag); - } - } - - /** - * Unique pointer id of the event - * - * @readonly - * @private - * @member {number} - */ - get pointerId(): number - { - return this._pointerId; - } - - /** - * State of the tracking data, expressed as bit flags - * - * @private - * @member {number} - */ - get flags(): number - { - return this._flags; - } - - set flags(flags: number) - { - this._flags = flags; - } - - /** - * Is the tracked event inactive (not over or down)? - * - * @private - * @member {number} - */ - get none(): boolean - { - return this._flags === InteractionTrackingData.FLAGS.NONE; - } - - /** - * Is the tracked event over the DisplayObject? - * - * @private - * @member {boolean} - */ - get over(): boolean - { - return (this._flags & InteractionTrackingData.FLAGS.OVER) !== 0; - } - - set over(yn: boolean) - { - this._doSet(InteractionTrackingData.FLAGS.OVER, yn); - } - - /** - * Did the right mouse button come down in the DisplayObject? - * - * @private - * @member {boolean} - */ - get rightDown(): boolean - { - return (this._flags & InteractionTrackingData.FLAGS.RIGHT_DOWN) !== 0; - } - - set rightDown(yn: boolean) - { - this._doSet(InteractionTrackingData.FLAGS.RIGHT_DOWN, yn); - } - - /** - * Did the left mouse button come down in the DisplayObject? - * - * @private - * @member {boolean} - */ - get leftDown(): boolean - { - return (this._flags & InteractionTrackingData.FLAGS.LEFT_DOWN) !== 0; - } - - set leftDown(yn: boolean) - { - this._doSet(InteractionTrackingData.FLAGS.LEFT_DOWN, yn); - } -} diff --git a/packages/interaction/src/TreeSearch.ts b/packages/interaction/src/TreeSearch.ts deleted file mode 100644 index f08817f1859..00000000000 --- a/packages/interaction/src/TreeSearch.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { Point } from '@pixi/math'; - -import type { InteractionEvent, InteractionCallback } from './InteractionEvent'; -import type { Container, DisplayObject } from '@pixi/display'; - -/** - * Strategy how to search through stage tree for interactive objects - * - * @memberof PIXI - */ -export class TreeSearch -{ - private readonly _tempPoint: Point; - - constructor() - { - this._tempPoint = new Point(); - } - - /** - * Recursive implementation for findHit - * - * @private - * @param interactionEvent - event containing the point that - * is tested for collision - * @param displayObject - the displayObject - * that will be hit test (recursively crawls its children) - * @param func - the function that will be called on each interactive object. The - * interactionEvent, displayObject and hit will be passed to the function - * @param hitTest - this indicates if the objects inside should be hit test against the point - * @param interactive - Whether the displayObject is interactive - * @return - Returns true if the displayObject hit the point - */ - public recursiveFindHit(interactionEvent: InteractionEvent, displayObject: DisplayObject, - func?: InteractionCallback, hitTest?: boolean, interactive?: boolean - ): boolean - { - if (!displayObject || !displayObject.visible) - { - return false; - } - - const point = interactionEvent.data.global; - - // Took a little while to rework this function correctly! But now it is done and nice and optimized! ^_^ - // - // This function will now loop through all objects and then only hit test the objects it HAS - // to, not all of them. MUCH faster.. - // An object will be hit test if the following is true: - // - // 1: It is interactive. - // 2: It belongs to a parent that is interactive AND one of the parents children have not already been hit. - // - // As another little optimization once an interactive object has been hit we can carry on - // through the scenegraph, but we know that there will be no more hits! So we can avoid extra hit tests - // A final optimization is that an object is not hit test directly if a child has already been hit. - - interactive = displayObject.interactive || interactive; - - let hit = false; - let interactiveParent = interactive; - - // Flag here can set to false if the event is outside the parents hitArea or mask - let hitTestChildren = true; - - // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea - // There is also no longer a need to hitTest children. - if (displayObject.hitArea) - { - if (hitTest) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hitTest = false; - hitTestChildren = false; - } - else - { - hit = true; - } - } - interactiveParent = false; - } - // If there is a mask, no need to hitTest against anything else if the pointer is not within the mask. - // We still want to hitTestChildren, however, to ensure a mouseout can still be generated. - // https://github.com/pixijs/pixi.js/issues/5135 - else if (displayObject._mask) - { - if (hitTest) - { - if (!((displayObject._mask as any).containsPoint && (displayObject._mask as any).containsPoint(point))) - { - hitTest = false; - } - } - } - - // ** FREE TIP **! If an object is not interactive or has no buttons in it - // (such as a game scene!) set interactiveChildren to false for that displayObject. - // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (hitTestChildren && displayObject.interactiveChildren && (displayObject as Container).children) - { - const children = (displayObject as Container).children; - - for (let i = children.length - 1; i >= 0; i--) - { - const child = children[i]; - - // time to get recursive.. if this function will return if something is hit.. - const childHit = this.recursiveFindHit(interactionEvent, child, func, hitTest, interactiveParent); - - if (childHit) - { - // its a good idea to check if a child has lost its parent. - // this means it has been removed whilst looping so its best - if (!child.parent) - { - continue; - } - - // we no longer need to hit test any more objects in this container as we we - // now know the parent has been hit - interactiveParent = false; - - // If the child is interactive , that means that the object hit was actually - // interactive and not just the child of an interactive object. - // This means we no longer need to hit test anything else. We still need to run - // through all objects, but we don't need to perform any hit tests. - - if (childHit) - { - if (interactionEvent.target) - { - hitTest = false; - } - hit = true; - } - } - } - } - - // no point running this if the item is not interactive or does not have an interactive parent. - if (interactive) - { - // if we are hit testing (as in we have no hit any objects yet) - // We also don't need to worry about hit testing if once of the displayObjects children - // has already been hit - but only if it was interactive, otherwise we need to keep - // looking for an interactive child, just in case we hit one - if (hitTest && !interactionEvent.target) - { - // already tested against hitArea if it is defined - if (!displayObject.hitArea && (displayObject as any).containsPoint) - { - if ((displayObject as any).containsPoint(point)) - { - hit = true; - } - } - } - - if (displayObject.interactive) - { - if (hit && !interactionEvent.target) - { - interactionEvent.target = displayObject; - } - - if (func) - { - func(interactionEvent, displayObject, !!hit); - } - } - } - - return hit; - } - - /** - * This function is provides a neat way of crawling through the scene graph and running a - * specified function on all interactive objects it finds. It will also take care of hit - * testing the interactive objects and passes the hit across in the function. - * - * @private - * @param interactionEvent - event containing the point that - * is tested for collision - * @param displayObject - the displayObject - * that will be hit test (recursively crawls its children) - * @param func - the function that will be called on each interactive object. The - * interactionEvent, displayObject and hit will be passed to the function - * @param hitTest - this indicates if the objects inside should be hit test against the point - * @return - Returns true if the displayObject hit the point - */ - public findHit(interactionEvent: InteractionEvent, displayObject: DisplayObject, - func?: InteractionCallback, hitTest?: boolean - ): void - { - this.recursiveFindHit(interactionEvent, displayObject, func, hitTest, false); - } -} diff --git a/packages/interaction/src/index.ts b/packages/interaction/src/index.ts deleted file mode 100644 index 293e4de7fb5..00000000000 --- a/packages/interaction/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './InteractionData'; -export * from './InteractionManager'; -export * from './interactiveTarget'; -export * from './InteractionTrackingData'; -export * from './InteractionEvent'; diff --git a/packages/interaction/src/interactiveTarget.ts b/packages/interaction/src/interactiveTarget.ts deleted file mode 100644 index baa28049c57..00000000000 --- a/packages/interaction/src/interactiveTarget.ts +++ /dev/null @@ -1,162 +0,0 @@ -import type { InteractionTrackingData } from './InteractionTrackingData'; - -type Cursor = 'auto' - | 'default' - | 'none' - | 'context-menu' - | 'help' - | 'pointer' - | 'progress' - | 'wait' - | 'cell' - | 'crosshair' - | 'text' - | 'vertical-text' - | 'alias' - | 'copy' - | 'move' - | 'no-drop' - | 'not-allowed' - | 'e-resize' - | 'n-resize' - | 'ne-resize' - | 'nw-resize' - | 's-resize' - | 'se-resize' - | 'sw-resize' - | 'w-resize' - | 'ns-resize' - | 'ew-resize' - | 'nesw-resize' - | 'col-resize' - | 'nwse-resize' - | 'row-resize' - | 'all-scroll' - | 'zoom-in' - | 'zoom-out' - | 'grab' - | 'grabbing'; - -export interface IHitArea { - contains(x: number, y: number): boolean; -} - -export interface InteractiveTarget { - interactive: boolean; - interactiveChildren: boolean; - hitArea: IHitArea | null; - cursor: Cursor | string; - buttonMode: boolean; - trackedPointers: {[x: number]: InteractionTrackingData}; - _trackedPointers: {[x: number]: InteractionTrackingData}; -} - -/** - * Interface for classes that represent a hit area. - * - * It is implemented by the following classes: - * - {@link PIXI.Circle} - * - {@link PIXI.Ellipse} - * - {@link PIXI.Polygon} - * - {@link PIXI.RoundedRectangle} - * - * @interface IHitArea - * @memberof PIXI - */ - -/** - * Checks whether the x and y coordinates given are contained within this area - * - * @method - * @name contains - * @memberof PIXI.IHitArea# - * @param {number} x - The X coordinate of the point to test - * @param {number} y - The Y coordinate of the point to test - * @return {boolean} Whether the x/y coordinates are within this area - */ - -/** - * Default property values of interactive objects - * Used by {@link PIXI.InteractionManager} to automatically give all DisplayObjects these properties - * - * @private - * @name interactiveTarget - * @type {Object} - * @memberof PIXI - * @example - * function MyObject() {} - * - * Object.assign( - * DisplayObject.prototype, - * PIXI.interactiveTarget - * ); - */ -export const interactiveTarget: InteractiveTarget = { - interactive: false, - interactiveChildren: true, - hitArea: null, - - /** - * If enabled, the mouse cursor use the pointer behavior when hovered over the displayObject if it is interactive - * Setting this changes the 'cursor' property to `'pointer'`. - * - * @example - * const sprite = new PIXI.Sprite(texture); - * sprite.interactive = true; - * sprite.buttonMode = true; - * @member {boolean} - * @memberof PIXI.DisplayObject# - */ - get buttonMode(): boolean - { - return this.cursor === 'pointer'; - }, - set buttonMode(value: boolean) - { - if (value) - { - this.cursor = 'pointer'; - } - else if (this.cursor === 'pointer') - { - this.cursor = null; - } - }, - - /** - * This defines what cursor mode is used when the mouse cursor - * is hovered over the displayObject. - * - * @example - * const sprite = new PIXI.Sprite(texture); - * sprite.interactive = true; - * sprite.cursor = 'wait'; - * @see https://developer.mozilla.org/en/docs/Web/CSS/cursor - * - * @member {string} - * @memberof PIXI.DisplayObject# - */ - cursor: null, - - /** - * Internal set of all active pointers, by identifier - * - * @member {Map} - * @memberof PIXI.DisplayObject# - * @private - */ - get trackedPointers() - { - if (this._trackedPointers === undefined) this._trackedPointers = {}; - - return this._trackedPointers; - }, - - /** - * Map of all tracked pointers, by identifier. Use trackedPointers to access. - * - * @private - * @type {Map} - */ - _trackedPointers: undefined, -}; diff --git a/packages/interaction/test/InteractionData.tests.ts b/packages/interaction/test/InteractionData.tests.ts deleted file mode 100755 index ac3d46e1742..00000000000 --- a/packages/interaction/test/InteractionData.tests.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { InteractionData } from '@pixi/interaction'; -import { DisplayObject } from '@pixi/display'; -import { Point } from '@pixi/math'; -import { expect } from 'chai'; - -import '@pixi/canvas-display'; - -describe('InteractionData', function () -{ - describe('getLocalPosition', function () - { - it('should populate second parameter with result', function () - { - const data = new InteractionData(); - const stage = new DisplayObject(); - const displayObject = new DisplayObject(); - const point = new Point(); - - data.global.set(10, 10); - displayObject.position.set(5, 3); - displayObject.parent = stage; - displayObject.displayObjectUpdateTransform(); - data.getLocalPosition(displayObject, point); - expect(point.x).to.equal(5); - expect(point.y).to.equal(7); - }); - }); -}); diff --git a/packages/interaction/test/InteractionManager.tests.ts b/packages/interaction/test/InteractionManager.tests.ts deleted file mode 100644 index e3bbbb0dd05..00000000000 --- a/packages/interaction/test/InteractionManager.tests.ts +++ /dev/null @@ -1,2174 +0,0 @@ -import { MockPointer } from './MockPointer'; -import { Container } from '@pixi/display'; -import { Ticker } from '@pixi/ticker'; -import { Graphics } from '@pixi/graphics'; -import { Point, Rectangle } from '@pixi/math'; -import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { InteractionManager } from '@pixi/interaction'; -import { CanvasGraphicsRenderer } from '@pixi/canvas-graphics'; -import { CanvasSpriteRenderer } from '@pixi/canvas-sprite'; -import { Sprite } from '@pixi/sprite'; -import sinon from 'sinon'; -import { expect } from 'chai'; - -import '@pixi/canvas-display'; - -CanvasRenderer.registerPlugin('interaction', InteractionManager); -CanvasRenderer.registerPlugin('graphics', CanvasGraphicsRenderer); -CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer); - -describe('InteractionManager', function () -{ - afterEach(function () - { - // if we made a MockPointer for the test, clean it up - if (this.pointer) - { - this.pointer.cleanUp(); - this.pointer = null; - } - }); - - describe('event basics', function () - { - it('should call mousedown handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mousedown', eventSpy); - - pointer.mousedown(10, 10); - - expect(eventSpy).to.have.been.calledOnce; - }); - - it('should call mouseup handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseup', eventSpy); - - pointer.click(10, 10); - - expect(eventSpy).to.have.been.called; - }); - - it('should call mouseupoutside handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseupoutside', eventSpy); - - pointer.mousedown(10, 10); - pointer.mouseup(60, 60); - - expect(eventSpy).to.have.been.called; - }); - - it('should call mouseupoutside handler on mouseup on different elements', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseupoutside', eventSpy); - - pointer.mousedown(10, 10); - pointer.mouseup(10, 10, false); - - expect(eventSpy).to.have.been.called; - }); - - it('should call mouseover handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseover', eventSpy); - - pointer.mousemove(10, 10); - - expect(eventSpy).to.have.been.called; - }); - - it('should call mouseout handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseout', eventSpy); - - pointer.mousemove(10, 10); - pointer.mousemove(60, 60); - - expect(eventSpy).to.have.been.called; - }); - - it('should always call mouseout before mouseover', function () - { - const stage = new Container(); - const graphicsA = new Graphics(); - const graphicsB = new Graphics(); - - const mouseOverSpyA = sinon.spy(); - const mouseOutSpyA = sinon.spy(); - - const mouseOverSpyB = sinon.spy(); - const mouseOutSpyB = sinon.spy(); - - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphicsA); - graphicsA.beginFill(0xFFFFFF); - graphicsA.drawRect(0, 0, 50, 50); - graphicsA.interactive = true; - - graphicsA.on('mouseover', mouseOverSpyA); - graphicsA.on('mouseout', mouseOutSpyA); - - stage.addChild(graphicsB); - graphicsB.x = 25; - graphicsB.beginFill(0xFFFFFF); - graphicsB.drawRect(0, 0, 50, 50); - graphicsB.interactive = true; - - graphicsB.on('mouseover', mouseOverSpyB); - graphicsB.on('mouseout', mouseOutSpyB); - - pointer.mousemove(10, 10); - - expect(mouseOverSpyA).to.have.been.called; - - pointer.mousemove(40, 10); - - expect(mouseOutSpyA).to.have.been.calledImmediatelyBefore(mouseOverSpyB); - - pointer.mousemove(10, 10); - - expect(mouseOutSpyB).to.have.been.calledImmediatelyBefore(mouseOverSpyA); - }); - }); - - describe('event propagation', function () - { - it('should stop event propagation', function () - { - const stage = new Container(); - const parent = new Container(); - const graphics = new Graphics(); - - const pointer = this.pointer = new MockPointer(stage); - - const mouseDownChild = sinon.spy((evt) => evt.stopPropagation()); - const mouseDownParent = sinon.spy(); - - stage.addChild(parent); - parent.addChild(graphics); - - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - parent.interactive = true; - - graphics.on('mousedown', mouseDownChild); - - parent.on('mousedown', mouseDownParent); - - pointer.mousedown(10, 10); - - expect(mouseDownChild).to.have.been.called; - expect(mouseDownParent).to.not.have.been.called; - }); - - it('should not stop events on the same object from happening', function () - { - const stage = new Container(); - const parent = new Container(); - const graphics = new Graphics(); - - const pointer = this.pointer = new MockPointer(stage); - - // Neither of these should stop the other from firing - const mouseMoveChild = sinon.spy((evt) => evt.stopPropagation()); - const mouseOverChild = sinon.spy((evt) => evt.stopPropagation()); - - const mouseMoveParent = sinon.spy(); - const mouseOverParent = sinon.spy(); - - stage.addChild(parent); - parent.addChild(graphics); - - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - parent.interactive = true; - - graphics.on('mousemove', mouseMoveChild); - graphics.on('mouseover', mouseOverChild); - - parent.on('mousemove', mouseMoveParent); - parent.on('mouseover', mouseOverParent); - - pointer.mousemove(10, 10); - - expect(mouseOverChild).to.have.been.called; - expect(mouseMoveChild).to.have.been.called; - - expect(mouseOverParent).to.not.have.been.called; - expect(mouseMoveParent).to.not.have.been.called; - }); - - it('should not stop events on children of an object from happening', function () - { - const stage = new Container(); - const parent = new Container(); - const graphics = new Graphics(); - - const pointer = this.pointer = new MockPointer(stage); - - const mouseMoveChild = sinon.spy(); - const mouseMoveParent = sinon.spy((evt) => evt.stopPropagation()); - - const mouseOverChild = sinon.spy(); - const mouseOverParent = sinon.spy(); - - stage.addChild(parent); - parent.addChild(graphics); - - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - parent.interactive = true; - - graphics.on('mousemove', mouseMoveChild); - graphics.on('mouseover', mouseOverChild); - - parent.on('mousemove', mouseMoveParent); - parent.on('mouseover', mouseOverParent); - - pointer.mousemove(10, 10); - - expect(mouseMoveChild).to.have.been.called; - expect(mouseOverChild).to.have.been.called; - - expect(mouseMoveParent).to.have.been.called; - expect(mouseOverParent).to.have.been.called; - }); - }); - - describe('touch vs pointer', function () - { - it('should call touchstart and pointerdown when touch event and pointer supported', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const touchSpy = sinon.spy(function touchListen() { /* noop */ }); - const pointerSpy = sinon.spy(function pointerListen() { /* noop */ }); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('touchstart', touchSpy); - graphics.on('pointerdown', pointerSpy); - - pointer.touchstart(10, 10); - - expect(touchSpy).to.have.been.calledOnce; - expect(pointerSpy).to.have.been.calledOnce; - }); - - it('should not call touchstart or pointerdown when pointer event and touch supported', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const touchSpy = sinon.spy(function touchListen() { /* noop */ }); - const pointerSpy = sinon.spy(function pointerListen() { /* noop */ }); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('touchstart', touchSpy); - graphics.on('pointerdown', pointerSpy); - - pointer.touchstart(10, 10, 0, true); - - expect(touchSpy).to.not.have.been.called; - expect(pointerSpy).to.not.have.been.called; - }); - - it('should call touchstart and pointerdown when touch event and pointer not supported', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const touchSpy = sinon.spy(function touchListen() { /* noop */ }); - const pointerSpy = sinon.spy(function pointerListen() { /* noop */ }); - const pointer = this.pointer = new MockPointer(stage, null, null, false); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('touchstart', touchSpy); - graphics.on('pointerdown', pointerSpy); - - pointer.touchstart(10, 10); - - expect(touchSpy).to.have.been.calledOnce; - expect(pointerSpy).to.have.been.calledOnce; - }); - - it('should call touchstart and pointerdown when pointer event and touch not supported', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const touchSpy = sinon.spy(function touchListen() { /* noop */ }); - const pointerSpy = sinon.spy(function pointerListen() { /* noop */ }); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - pointer.interaction.supportsTouchEvents = false; - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('touchstart', touchSpy); - graphics.on('pointerdown', pointerSpy); - - pointer.touchstart(10, 10, 0, true); - - expect(touchSpy).to.have.been.calledOnce; - expect(pointerSpy).to.have.been.calledOnce; - }); - }); - - describe('add/remove events and ticker', function () - { - let stub; - - before(function () - { - stub = sinon.stub(InteractionManager.prototype, 'setTargetElement'); - }); - - after(function () - { - stub.restore(); - }); - - it('should add and remove pointer events to document', function () - { - const manager = new InteractionManager(sinon.stub()); - const addSpy = sinon.spy(window.document, 'addEventListener'); - const removeSpy = sinon.spy(window.document, 'removeEventListener'); - - manager.interactionDOMElement = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - manager.supportsPointerEvents = true; - - manager.addEvents(); - - expect(addSpy).to.have.been.calledOnce; - expect(addSpy).to.have.been.calledWith('pointermove'); - - manager.removeEvents(); - - expect(removeSpy).to.have.been.calledOnce; - expect(removeSpy).to.have.been.calledWith('pointermove'); - - addSpy.restore(); - removeSpy.restore(); - }); - - it('should add and remove pointer events to window', function () - { - const manager = new InteractionManager(sinon.stub()); - const addSpy = sinon.spy(window, 'addEventListener'); - const removeSpy = sinon.spy(window, 'removeEventListener'); - - manager.interactionDOMElement = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - manager.supportsPointerEvents = true; - - manager.addEvents(); - - expect(addSpy).to.have.been.calledTwice; - expect(addSpy).to.have.been.calledWith('pointercancel'); - expect(addSpy).to.have.been.calledWith('pointerup'); - - manager.removeEvents(); - - expect(removeSpy).to.have.been.calledTwice; - expect(removeSpy).to.have.been.calledWith('pointercancel'); - expect(removeSpy).to.have.been.calledWith('pointerup'); - - addSpy.restore(); - removeSpy.restore(); - }); - - it('should add and remove pointer events to element seven times when touch events are supported', function () - { - const manager = new InteractionManager(sinon.stub()); - const element = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - - manager.interactionDOMElement = element; - manager.supportsPointerEvents = true; - manager.supportsTouchEvents = true; - - manager.addEvents(); - - expect(element.addEventListener).to.have.been.callCount(7); - expect(element.addEventListener).to.have.been.calledWith('pointerdown'); - expect(element.addEventListener).to.have.been.calledWith('pointerleave'); - expect(element.addEventListener).to.have.been.calledWith('pointerover'); - - expect(element.addEventListener).to.have.been.calledWith('touchstart'); - expect(element.addEventListener).to.have.been.calledWith('touchcancel'); - expect(element.addEventListener).to.have.been.calledWith('touchend'); - expect(element.addEventListener).to.have.been.calledWith('touchmove'); - - manager.removeEvents(); - - expect(element.removeEventListener).to.have.been.callCount(7); - expect(element.removeEventListener).to.have.been.calledWith('pointerdown'); - expect(element.removeEventListener).to.have.been.calledWith('pointerleave'); - expect(element.removeEventListener).to.have.been.calledWith('pointerover'); - - expect(element.removeEventListener).to.have.been.calledWith('touchstart'); - expect(element.removeEventListener).to.have.been.calledWith('touchcancel'); - expect(element.removeEventListener).to.have.been.calledWith('touchend'); - expect(element.removeEventListener).to.have.been.calledWith('touchmove'); - }); - - it('should add and remove pointer events to element three times when touch events are not supported', function () - { - const manager = new InteractionManager(sinon.stub()); - const element = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - - manager.interactionDOMElement = element; - manager.supportsPointerEvents = true; - manager.supportsTouchEvents = false; - - manager.addEvents(); - - expect(element.addEventListener).to.have.been.calledThrice; - expect(element.addEventListener).to.have.been.calledWith('pointerdown'); - expect(element.addEventListener).to.have.been.calledWith('pointerleave'); - expect(element.addEventListener).to.have.been.calledWith('pointerover'); - - manager.removeEvents(); - - expect(element.removeEventListener).to.have.been.calledThrice; - expect(element.removeEventListener).to.have.been.calledWith('pointerdown'); - expect(element.removeEventListener).to.have.been.calledWith('pointerleave'); - expect(element.removeEventListener).to.have.been.calledWith('pointerover'); - }); - - it('should add and remove mouse events to document', function () - { - const manager = new InteractionManager(sinon.stub()); - const addSpy = sinon.spy(window.document, 'addEventListener'); - const removeSpy = sinon.spy(window.document, 'removeEventListener'); - - manager.interactionDOMElement = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - manager.supportsPointerEvents = false; - - manager.addEvents(); - - expect(addSpy).to.have.been.calledOnce; - expect(addSpy).to.have.been.calledWith('mousemove'); - - manager.removeEvents(); - - expect(removeSpy).to.have.been.calledOnce; - expect(removeSpy).to.have.been.calledWith('mousemove'); - - addSpy.restore(); - removeSpy.restore(); - }); - - it('should add and remove mouse events to window', function () - { - const manager = new InteractionManager(sinon.stub()); - const addSpy = sinon.spy(window, 'addEventListener'); - const removeSpy = sinon.spy(window, 'removeEventListener'); - - manager.interactionDOMElement = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - manager.supportsPointerEvents = false; - - manager.addEvents(); - - expect(addSpy).to.have.been.calledOnce; - expect(addSpy).to.have.been.calledWith('mouseup'); - - manager.removeEvents(); - - expect(removeSpy).to.have.been.calledOnce; - expect(removeSpy).to.have.been.calledWith('mouseup'); - - addSpy.restore(); - removeSpy.restore(); - }); - - it('should add and remove mouse events to element', function () - { - const manager = new InteractionManager(sinon.stub()); - const element = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - - manager.interactionDOMElement = element; - manager.supportsPointerEvents = false; - manager.supportsTouchEvents = false; - - manager.addEvents(); - - expect(element.addEventListener).to.have.been.calledThrice; - expect(element.addEventListener).to.have.been.calledWith('mousedown'); - expect(element.addEventListener).to.have.been.calledWith('mouseout'); - expect(element.addEventListener).to.have.been.calledWith('mouseover'); - - manager.removeEvents(); - - expect(element.removeEventListener).to.have.been.calledThrice; - expect(element.removeEventListener).to.have.been.calledWith('mousedown'); - expect(element.removeEventListener).to.have.been.calledWith('mouseout'); - expect(element.removeEventListener).to.have.been.calledWith('mouseover'); - }); - - it('should add and remove touch events to element without pointer events', function () - { - const manager = new InteractionManager(sinon.stub()); - const element = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - - manager.interactionDOMElement = element; - manager.supportsPointerEvents = false; - manager.supportsTouchEvents = true; - - manager.addEvents(); - - expect(element.addEventListener).to.have.been.calledWith('touchstart'); - expect(element.addEventListener).to.have.been.calledWith('touchcancel'); - expect(element.addEventListener).to.have.been.calledWith('touchend'); - expect(element.addEventListener).to.have.been.calledWith('touchmove'); - - manager.removeEvents(); - - expect(element.removeEventListener).to.have.been.calledWith('touchstart'); - expect(element.removeEventListener).to.have.been.calledWith('touchcancel'); - expect(element.removeEventListener).to.have.been.calledWith('touchend'); - expect(element.removeEventListener).to.have.been.calledWith('touchmove'); - }); - - it('should add and remove touch events to element with pointer events', function () - { - const manager = new InteractionManager(sinon.stub()); - const element = { style: {}, addEventListener: sinon.stub(), removeEventListener: sinon.stub() }; - - manager.interactionDOMElement = element; - manager.supportsPointerEvents = true; - manager.supportsTouchEvents = true; - - manager.addEvents(); - - expect(element.addEventListener).to.have.been.calledWith('touchstart'); - expect(element.addEventListener).to.have.been.calledWith('touchcancel'); - expect(element.addEventListener).to.have.been.calledWith('touchend'); - expect(element.addEventListener).to.have.been.calledWith('touchmove'); - - manager.removeEvents(); - - expect(element.removeEventListener).to.have.been.calledWith('touchstart'); - expect(element.removeEventListener).to.have.been.calledWith('touchcancel'); - expect(element.removeEventListener).to.have.been.calledWith('touchend'); - expect(element.removeEventListener).to.have.been.calledWith('touchmove'); - }); - - it('should add and remove Ticker.system listener', function () - { - const manager = new InteractionManager(sinon.stub()); - - const element = {}; - - manager.interactionDOMElement = element; - - const listenerCount = Ticker.system.count; - - manager.addTickerListener(); - - expect(Ticker.system.count).to.equal(listenerCount + 1); - - manager.useSystemTicker = false; - - expect(Ticker.system.count).to.equal(listenerCount); - - manager.useSystemTicker = true; - - expect(Ticker.system.count).to.equal(listenerCount + 1); - - manager.removeTickerListener(); - - expect(Ticker.system.count).to.equal(listenerCount); - - manager.useSystemTicker = false; - - expect(Ticker.system.count).to.equal(listenerCount); - - manager.addTickerListener(); - - expect(Ticker.system.count).to.equal(listenerCount); - }); - }); - - describe('onClick', function () - { - it('should call handler when inside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('click', clickSpy); - - pointer.click(10, 10); - - expect(clickSpy).to.have.been.calledOnce; - }); - - it('should not call handler when outside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('click', clickSpy); - - pointer.click(60, 60); - - expect(clickSpy).to.not.have.been.called; - }); - - it('should not call handler when mousedown not received', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('click', clickSpy); - - pointer.mouseup(10, 10); - - expect(clickSpy, 'click should not happen on first mouseup').to.not.have.been.called; - - // test again, just because it was a bug that was reported - pointer.mouseup(20, 20); - - expect(clickSpy, 'click should not happen on second mouseup').to.not.have.been.called; - }); - }); - - describe('onTap', function () - { - it('should call handler when inside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('tap', clickSpy); - - pointer.tap(10, 10); - - expect(clickSpy).to.have.been.calledOnce; - }); - - it('should not call handler when outside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('tap', clickSpy); - - pointer.tap(60, 60); - - expect(clickSpy).to.not.have.been.called; - }); - - it('should not call handler when moved to other sprite', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const graphics2 = new Graphics(); - const clickSpy = sinon.spy(); - const overSpy = sinon.spy(); - const endSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.name = 'graphics1'; - - stage.addChild(graphics2); - graphics2.beginFill(0xFFFFFF); - graphics2.drawRect(75, 75, 50, 50); - graphics2.interactive = true; - graphics2.on('tap', clickSpy); - graphics2.on('touchmove', overSpy); - graphics2.on('touchend', endSpy); - graphics2.name = 'graphics2'; - - pointer.touchstart(25, 25, 3); - pointer.touchmove(60, 60, 3); - pointer.touchmove(80, 80, 3); - pointer.touchend(80, 80, 3); - - expect(overSpy).to.have.been.called; - expect(endSpy).to.have.been.called; - expect(clickSpy).to.not.have.been.called; - }); - }); - - describe('pointertap', function () - { - it('should call handler when inside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('pointertap', clickSpy); - - pointer.click(10, 10, true); - - expect(clickSpy).to.have.been.calledOnce; - }); - - it('should not call handler when outside', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('pointertap', clickSpy); - - pointer.click(60, 60, true); - - expect(clickSpy).to.not.have.been.called; - }); - - it('with mouse events, should not call handler when moved to other sprite', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const graphics2 = new Graphics(); - const overSpy = sinon.spy(); - const upSpy = sinon.spy(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.name = 'graphics1'; - - stage.addChild(graphics2); - graphics2.beginFill(0xFFFFFF); - graphics2.drawRect(75, 75, 50, 50); - graphics2.interactive = true; - graphics2.on('pointertap', clickSpy); - graphics2.on('pointerover', overSpy); - graphics2.on('pointerup', upSpy); - graphics2.name = 'graphics2'; - - pointer.mousedown(25, 25); - pointer.mousemove(60, 60); - pointer.mousemove(80, 80); - pointer.mouseup(80, 80); - - expect(overSpy).to.have.been.called; - expect(upSpy).to.have.been.called; - expect(clickSpy).to.not.have.been.called; - }); - - it('with pointer events, should not call handler when moved to other sprite', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const graphics2 = new Graphics(); - const overSpy = sinon.spy(); - const upSpy = sinon.spy(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.name = 'graphics1'; - - stage.addChild(graphics2); - graphics2.beginFill(0xFFFFFF); - graphics2.drawRect(75, 75, 50, 50); - graphics2.interactive = true; - graphics2.on('pointertap', clickSpy); - graphics2.on('pointerover', overSpy); - graphics2.on('pointerup', upSpy); - graphics2.name = 'graphics2'; - - pointer.mousedown(25, 25, true); - pointer.mousemove(60, 60, true); - pointer.mousemove(80, 80, true); - pointer.mouseup(80, 80, true); - - expect(overSpy).to.have.been.called; - expect(upSpy).to.have.been.called; - expect(clickSpy).to.not.have.been.called; - }); - - it('with touch events, should not call handler when moved to other sprite', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const graphics2 = new Graphics(); - const moveSpy = sinon.spy(); - const upSpy = sinon.spy(); - const clickSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.name = 'graphics1'; - - stage.addChild(graphics2); - graphics2.beginFill(0xFFFFFF); - graphics2.drawRect(75, 75, 50, 50); - graphics2.interactive = true; - graphics2.on('pointertap', clickSpy); - graphics2.on('pointermove', moveSpy); - graphics2.on('pointerup', upSpy); - graphics2.name = 'graphics2'; - - pointer.touchstart(25, 25, true); - pointer.touchmove(60, 60, true); - pointer.touchmove(80, 80, true); - pointer.touchend(80, 80, true); - - expect(moveSpy).to.have.been.called; - expect(upSpy).to.have.been.called; - expect(clickSpy).to.not.have.been.called; - }); - }); - - describe('overlapping children', function () - { - function getScene(callbackEventName, splitParents) - { - const behindChild = new Graphics(); - const frontChild = new Graphics(); - const parent = new Container(); - const behindChildCallback = sinon.spy(function behindSpy() { /* no op*/ }); - const frontChildCallback = sinon.spy(function frontSpy() { /* no op*/ }); - const parentCallback = sinon.spy(function parentSpy() { /* no op*/ }); - let behindParent; - let frontParent; - let behindParentCallback; - let frontParentCallback; - - behindChild.beginFill(0xFF); - behindChild.drawRect(0, 0, 50, 50); - behindChild.on(callbackEventName, behindChildCallback); - behindChild.name = 'behind'; - - frontChild.beginFill(0x00FF); - frontChild.drawRect(0, 0, 50, 50); - frontChild.on(callbackEventName, frontChildCallback); - frontChild.name = 'front'; - - if (splitParents) - { - behindParent = new Container(); - behindParent.name = 'behindParent'; - frontParent = new Container(); - frontParent.name = 'frontParent'; - behindParentCallback = sinon.spy(function behindParentSpy() { /* no op*/ }); - frontParentCallback = sinon.spy(function frontParentSpy() { /* no op*/ }); - behindParent.on(callbackEventName, behindParentCallback); - frontParent.on(callbackEventName, frontParentCallback); - - parent.addChild(behindParent, frontParent); - behindParent.addChild(behindChild); - frontParent.addChild(frontChild); - - parent.name = 'parent'; - } - else - { - parent.addChild(behindChild, frontChild); - } - parent.on(callbackEventName, parentCallback); - - return { - behindChild, - frontChild, - behindParent, - frontParent, - parent, - behindChildCallback, - frontChildCallback, - behindParentCallback, - frontParentCallback, - parentCallback, - }; - } - - describe('when parent is non-interactive', function () - { - describe('when both children are interactive', function () - { - it('should callback front child when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback front child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback behind child when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback front child of different non-interactive parents when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click', true); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - expect(scene.behindParentCallback).to.not.have.been.called; - expect(scene.frontParentCallback).to.not.have.been.called; - }); - - it('should callback front child of different interactive parents when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click', true); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.behindParent.interactive = true; - scene.frontParent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - expect(scene.behindParentCallback).to.not.have.been.called; - expect(scene.frontParentCallback).to.have.been.calledOnce; - }); - }); - - describe('when front child is non-interactive', function () - { - it('should not callback when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback behind child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback behind child when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - }); - - describe('when behind child is non-interactive', function () - { - it('should callback front child when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should callback front child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.not.have.been.called; - }); - - it('should not callback when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.not.have.been.called; - }); - }); - }); - - describe('when parent is interactive', function () - { - describe('when both children are interactive', function () - { - it('should callback parent and front child when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent and front child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent and behind child when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback front child of different non-interactive parents when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click', true); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - expect(scene.behindParentCallback).to.not.have.been.called; - expect(scene.frontParentCallback).to.not.have.been.called; - }); - - it('should callback front child of different interactive parents when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click', true); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - scene.behindParent.interactive = true; - scene.frontParent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - expect(scene.behindParentCallback).to.not.have.been.called; - expect(scene.frontParentCallback).to.have.been.calledOnce; - }); - }); - - describe('when front child is non-interactive', function () - { - it('should callback parent when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent and behind child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent and behind child when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.interactive = true; - scene.behindChild.x = 25; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - }); - - describe('when behind child is non-interactive', function () - { - it('should callback parent and front child when clicking front child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(10, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent and front child when clicking overlap', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(40, 10); - - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.frontChildCallback).to.have.been.calledOnce; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - - it('should callback parent when clicking behind child', function () - { - const stage = new Container(); - const pointer = this.pointer = new MockPointer(stage); - const scene = getScene('click'); - - scene.behindChild.x = 25; - scene.frontChild.interactive = true; - scene.parent.interactive = true; - - stage.addChild(scene.parent); - pointer.click(60, 10); - - expect(scene.frontChildCallback).to.not.have.been.called; - expect(scene.behindChildCallback).to.not.have.been.called; - expect(scene.parentCallback).to.have.been.calledOnce; - }); - }); - }); - - it('Semi-complicated nesting with overlap, should not call behind callback', function () - { - const stage = new Container(); - const frontParent = new Container(); - const frontChild = new Graphics(); - const behindParent = new Container(); - const subParent = new Container(); - const behindChild = new Graphics(); - const behindCallback = sinon.spy(function behindSpy() { /* no op*/ }); - const frontCallback = sinon.spy(function frontSpy() { /* no op*/ }); - - behindChild.beginFill(0xFF); - behindChild.drawRect(0, 0, 50, 50); - subParent.on('click', behindCallback); - - frontChild.beginFill(0x00FF); - frontChild.drawRect(0, 0, 50, 50); - frontParent.on('click', frontCallback); - const pointer = this.pointer = new MockPointer(stage); - - behindParent.x = 25; - subParent.interactive = true; - frontParent.interactive = true; - - behindParent.addChild(subParent); - subParent.addChild(behindChild); - stage.addChild(behindParent); - frontParent.addChild(frontChild); - stage.addChild(frontParent); - - pointer.click(40, 10); - - expect(behindCallback).to.not.have.been.called; - expect(frontCallback).to.have.been.calledOnce; - }); - }); - - describe('masks', function () - { - it('should trigger interaction callback when no mask present', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback on child when inside of parents mask', function () - { - const stage = new Container(); - const parent = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(parent); - parent.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 25, 25); - parent.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback on child when outside of parents mask', function () - { - const stage = new Container(); - const parent = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(parent); - parent.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 25, 25); - parent.mask = mask; - - pointer.click(30, 30); - - expect(spy).to.have.not.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const mask = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - }); - - describe('hitArea', function () - { - it('should trigger interaction callback when within hitArea', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - graphics.hitArea = new Rectangle(0, 0, 25, 25); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when not within hitArea', function () - { - const stage = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - graphics.hitArea = new Rectangle(0, 0, 25, 25); - - pointer.click(30, 30); - - expect(spy).to.have.not.been.calledOnce; - }); - - it('should trigger interaction callback on child when inside of parents hitArea', function () - { - const stage = new Container(); - const parent = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(parent); - parent.addChild(graphics); - parent.hitArea = new Rectangle(0, 0, 25, 25); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback on child when outside of parents hitArea', function () - { - const stage = new Container(); - const parent = new Container(); - const pointer = new MockPointer(stage); - const graphics = new Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(parent); - parent.addChild(graphics); - parent.hitArea = new Rectangle(0, 0, 25, 25); - - pointer.click(30, 30); - - expect(spy).to.have.not.been.calledOnce; - }); - }); - - describe('cursor changes', function () - { - it('cursor should be the cursor of interactive item', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = 'help'; - - pointer.mousemove(10, 10); - - expect(pointer.renderer.view.style.cursor).to.equal('help'); - }); - - it('should return cursor to default on mouseout', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = 'help'; - - pointer.mousemove(10, 10); - pointer.mousemove(60, 60); - - expect(pointer.renderer.view.style.cursor).to.equal(pointer.interaction.cursorStyles.default); - }); - - it('should still be the over cursor after a click', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = 'help'; - - pointer.mousemove(10, 10); - pointer.click(10, 10); - - expect(pointer.renderer.view.style.cursor).to.equal('help'); - }); - - it('should return cursor to default when mouse leaves renderer', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = 'help'; - - pointer.mousemove(10, 10); - pointer.mousemove(-10, 60); - - expect(pointer.renderer.view.style.cursor).to.equal(pointer.interaction.cursorStyles.default); - }); - - it('cursor callback should be called', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const overSpy = sinon.spy(); - const defaultSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = overSpy; - pointer.interaction.cursorStyles.default = defaultSpy; - - pointer.mousemove(10, 10); - pointer.mousemove(60, 60); - - expect(overSpy).to.have.been.called; - expect(defaultSpy).to.have.been.called; - }); - - it('cursor callback should only be called if the cursor actually changed', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const defaultSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = null; - pointer.interaction.cursorStyles.default = defaultSpy; - - pointer.mousemove(10, 10); - pointer.mousemove(20, 20); - - expect(defaultSpy).to.have.been.calledOnce; - }); - - it('cursor style object should be fully applied', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'help'; - pointer.interaction.cursorStyles.help = { - cursor: 'none', - display: 'none', - }; - - pointer.mousemove(10, 10); - - expect(pointer.renderer.view.style.cursor).to.equal('none'); - expect(pointer.renderer.view.style.display).to.equal('none'); - }); - - it('should not change cursor style if null cursor style provided', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'pointer'; - pointer.interaction.cursorStyles.pointer = null; - pointer.interaction.cursorStyles.default = null; - - pointer.mousemove(10, 10); - expect(pointer.renderer.view.style.cursor).to.equal(''); - - pointer.mousemove(60, 60); - expect(pointer.renderer.view.style.cursor).to.equal(''); - }); - - it('should use cursor property as css if no style entry', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.cursor = 'text'; - - pointer.mousemove(10, 10); - expect(pointer.renderer.view.style.cursor).to.equal('text'); - }); - }); - - describe('recursive hitTesting', function () - { - function getScene() - { - const stage = new Container(); - const behindChild = new Graphics(); - const middleChild = new Graphics(); - const frontChild = new Graphics(); - - behindChild.beginFill(0xFF); - behindChild.drawRect(0, 0, 50, 50); - - middleChild.beginFill(0xFF00); - middleChild.drawRect(0, 0, 50, 50); - - frontChild.beginFill(0xFF0000); - frontChild.drawRect(0, 0, 50, 50); - - stage.addChild(behindChild, middleChild, frontChild); - - return { - behindChild, - middleChild, - frontChild, - stage, - }; - } - - describe('when frontChild is interactive', function () - { - it('should stop hitTesting after first hit', function () - { - const scene = getScene(); - const pointer = this.pointer = new MockPointer(scene.stage); - const frontHitTest = sinon.spy(scene.frontChild, 'containsPoint'); - const middleHitTest = sinon.spy(scene.middleChild, 'containsPoint'); - const behindHitTest = sinon.spy(scene.behindChild, 'containsPoint'); - - scene.frontChild.interactive = true; - scene.middleChild.interactive = true; - scene.behindChild.interactive = true; - - pointer.mousedown(25, 25); - - expect(frontHitTest).to.have.been.calledOnce; - expect(middleHitTest).to.not.have.been.called; - expect(behindHitTest).to.not.have.been.called; - }); - }); - - describe('when frontChild is not interactive', function () - { - it('should stop hitTesting after first hit', function () - { - const scene = getScene(); - const pointer = this.pointer = new MockPointer(scene.stage); - const frontHitTest = sinon.spy(scene.frontChild, 'containsPoint'); - const middleHitTest = sinon.spy(scene.middleChild, 'containsPoint'); - const behindHitTest = sinon.spy(scene.behindChild, 'containsPoint'); - - scene.frontChild.interactive = false; - scene.middleChild.interactive = true; - scene.behindChild.interactive = true; - - pointer.mousedown(25, 25); - - expect(frontHitTest).to.not.have.been.called; - expect(middleHitTest).to.have.been.calledOnce; - expect(behindHitTest).to.not.have.been.called; - }); - }); - }); - - describe('pointer handling', function () - { - it('pointer event from mouse should use single mouse data', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage, 100, 100, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - - pointer.mousemove(20, 10, true); - - expect(pointer.interaction.mouse.global.x).to.equal(20); - expect(pointer.interaction.mouse.global.y).to.equal(10); - }); - }); - - describe('data cleanup', function () - { - it('touchleave after touchout should not orphan data', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - - pointer.touchstart(10, 10, 42); - expect(pointer.interaction.activeInteractionData[42]).to.exist; - pointer.touchend(10, 10, 42); - expect(pointer.interaction.activeInteractionData[42]).to.be.undefined; - pointer.touchleave(10, 10, 42); - expect(pointer.interaction.activeInteractionData[42]).to.be.undefined; - }); - }); - - describe('hitTest()', function () - { - it('should return hit', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - - pointer.render(); - const hit = pointer.interaction.hitTest(new Point(10, 10)); - - expect(hit).to.equal(graphics); - }); - - it('should return null if not hit', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - - pointer.render(); - const hit = pointer.interaction.hitTest(new Point(60, 60)); - - expect(hit).to.be.null; - }); - - it('should return top thing that was hit', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const behind = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(behind); - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - behind.beginFill(0xFFFFFF); - behind.drawRect(0, 0, 50, 50); - behind.interactive = true; - - pointer.render(); - const hit = pointer.interaction.hitTest(new Point(10, 10)); - - expect(hit).to.equal(graphics); - }); - - it('should return hit when passing in root', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const behind = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(behind); - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - behind.beginFill(0xFFFFFF); - behind.drawRect(0, 0, 50, 50); - behind.interactive = true; - - pointer.render(); - const hit = pointer.interaction.hitTest(new Point(10, 10), behind); - - expect(hit).to.equal(behind); - }); - }); - - describe('InteractionData properties', function () - { - it('isPrimary should be set for first touch only', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const pointer = this.pointer = new MockPointer(stage); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - - pointer.touchstart(10, 10, 1); - expect(pointer.interaction.activeInteractionData[1]).to.exist; - expect(pointer.interaction.activeInteractionData[1].isPrimary, - 'first touch should be primary on touch start').to.be.true; - pointer.touchstart(13, 9, 2); - expect(pointer.interaction.activeInteractionData[2].isPrimary, - 'second touch should not be primary').to.be.false; - pointer.touchmove(10, 20, 1); - expect(pointer.interaction.activeInteractionData[1].isPrimary, - 'first touch should still be primary after move').to.be.true; - pointer.touchend(10, 10, 1); - pointer.touchmove(13, 29, 2); - expect(pointer.interaction.activeInteractionData[2].isPrimary, - 'second touch should still not be primary after first is done').to.be.false; - }); - }); - - describe('mouse events from pens', function () - { - it('should call mousedown handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mousedown', eventSpy); - - pointer.pendown(10, 10); - - expect(eventSpy).to.have.been.calledOnce; - }); - - it('should call mousemove handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mousemove', eventSpy); - - pointer.penmove(10, 10); - - expect(eventSpy).to.have.been.calledOnce; - }); - - it('should call mouseup handler', function () - { - const stage = new Container(); - const graphics = new Graphics(); - const eventSpy = sinon.spy(); - const pointer = this.pointer = new MockPointer(stage, null, null, true); - - stage.addChild(graphics); - graphics.beginFill(0xFFFFFF); - graphics.drawRect(0, 0, 50, 50); - graphics.interactive = true; - graphics.on('mouseup', eventSpy); - - pointer.penup(10, 10); - - expect(eventSpy).to.have.been.calledOnce; - }); - }); -}); diff --git a/packages/interaction/test/MockPointer.ts b/packages/interaction/test/MockPointer.ts deleted file mode 100644 index 93959684a55..00000000000 --- a/packages/interaction/test/MockPointer.ts +++ /dev/null @@ -1,323 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { CanvasRenderer } from '@pixi/canvas-renderer'; -import { Ticker } from '@pixi/ticker'; -import { Rectangle } from '@pixi/math'; -import sinon from 'sinon'; - -const { system } = Ticker; - -/** - * Use this to mock mouse/touch/pointer events - * - * @class - */ -class MockPointer -{ - /** - * @param {PIXI.Container} stage - The root of the scene tree - * @param {number} [width=100] - Width of the renderer - * @param {number} [height=100] - Height of the renderer - * @param {boolean} [ensurePointerEvents=false] - If we should make sure that PointerEvents are 'supported' - */ - constructor(stage, width, height, ensurePointerEvents) - { - // fake PointerEvent existing - if (ensurePointerEvents && !window.PointerEvent) - { - window.PointerEvent = class PointerEvent extends MouseEvent - { - // eslint-disable-next-line - constructor(type, opts) - { - super(type, opts); - this.pointerType = opts.pointerType; - } - }; - this.createdPointerEvent = true; - } - - this.activeTouches = []; - this.stage = stage; - this.renderer = new CanvasRenderer(width || 100, height || 100); - this.renderer.sayHello = () => { /* empty */ }; - this.interaction = this.renderer.plugins.interaction; - this.interaction.supportsTouchEvents = true; - system.remove(this.interaction.update, this.interaction); - } - - /** - * Cleans up after tests - */ - cleanup() - { - if (this.createdPointerEvent) - { - delete window.PointerEvent; - } - this.renderer.destroy(); - } - - /** - * @private - * @param {number} x - pointer x position - * @param {number} y - pointer y position - */ - setPosition(x, y) - { - this.renderer.plugins.interaction.mapPositionToPoint = (point) => - { - point.x = x; - point.y = y; - }; - } - - /** - * @private - */ - render() - { - this.renderer.render(this.stage); - } - - /** - * [createEvent description] - * @param {string} eventType `type` of event - * @param {number} x pointer x position - * @param {number} y pointer y position - * @param {number} [identifier] pointer id for touch events - * @param {boolean} [asPointer] If it should be a PointerEvent from a mouse or touch - * @param {boolean} [onCanvas=true] If the event should be on the canvas (as opposed to a different element) - * @return {Event} Generated MouseEvent, TouchEvent, or PointerEvent - */ - createEvent(eventType, x, y, identifier, asPointer, onCanvas = true) - { - let event; - - if (eventType.startsWith('mouse')) - { - if (asPointer) - { - event = new PointerEvent(eventType.replace('mouse', 'pointer'), { - pointerType: 'mouse', - clientX: x, - clientY: y, - preventDefault: sinon.stub(), - }); - } - else - { - event = new MouseEvent(eventType, { - clientX: x, - clientY: y, - preventDefault: sinon.stub(), - }); - } - if (onCanvas) - { - Object.defineProperty(event, 'target', { value: this.renderer.view }); - } - } - else if (eventType.startsWith('touch')) - { - if (asPointer) - { - eventType = eventType.replace('touch', 'pointer').replace('start', 'down').replace('end', 'up'); - event = new PointerEvent(eventType, { - pointerType: 'touch', - pointerId: identifier || 0, - clientX: x, - clientY: y, - preventDefault: sinon.stub(), - }); - Object.defineProperty(event, 'target', { value: this.renderer.view }); - } - else - { - const touch = new Touch({ identifier: identifier || 0, target: this.renderer.view }); - - if (eventType.endsWith('start')) - { - this.activeTouches.push(touch); - } - else if (eventType.endsWith('end') || eventType.endsWith('leave')) - { - for (let i = 0; i < this.activeTouches.length; ++i) - { - if (this.activeTouches[i].identifier === touch.identifier) - { - this.activeTouches.splice(i, 1); - break; - } - } - } - event = new TouchEvent(eventType, { - preventDefault: sinon.stub(), - changedTouches: [touch], - touches: this.activeTouches, - }); - - Object.defineProperty(event, 'target', { value: this.renderer.view }); - } - } - else - { - event = new PointerEvent(eventType, { - pointerType: 'pen', - pointerId: identifier || 0, - clientX: x, - clientY: y, - preventDefault: sinon.stub(), - }); - Object.defineProperty(event, 'target', { value: this.renderer.view }); - } - - this.setPosition(x, y); - this.render(); - - return event; - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {boolean} [asPointer] - if it should be a PointerEvent from a mouse - */ - mousemove(x, y, asPointer) - { - // mouseOverRenderer state should be correct, so mouse position to view rect - const rect = new Rectangle(0, 0, this.renderer.width, this.renderer.height); - - if (rect.contains(x, y)) - { - if (!this.interaction.mouseOverRenderer) - { - this.interaction.onPointerOver(this.createEvent('mouseover', x, y, null, asPointer)); - } - this.interaction.onPointerMove(this.createEvent('mousemove', x, y, null, asPointer)); - } - else - { - this.interaction.onPointerOut(this.createEvent('mouseout', x, y, null, asPointer)); - } - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {boolean} [asPointer] - if it should be a PointerEvent from a mouse - */ - click(x, y, asPointer) - { - this.mousedown(x, y, asPointer); - this.mouseup(x, y, asPointer); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {boolean} [asPointer] - if it should be a PointerEvent from a mouse - */ - mousedown(x, y, asPointer) - { - this.interaction.onPointerDown(this.createEvent('mousedown', x, y, null, asPointer)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {boolean} [onCanvas=true] - if the event happened on the Canvas element or not - * @param {boolean} [asPointer] - if it should be a PointerEvent from a mouse - */ - mouseup(x, y, onCanvas = true, asPointer = false) - { - this.interaction.onPointerUp(this.createEvent('mouseup', x, y, null, asPointer, onCanvas)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - * @param {boolean} [asPointer] - if it should be a PointerEvent from a touch - */ - tap(x, y, identifier, asPointer) - { - this.touchstart(x, y, identifier, asPointer); - this.touchend(x, y, identifier, asPointer); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - * @param {boolean} [asPointer] - if it should be a PointerEvent from a touch - */ - touchstart(x, y, identifier, asPointer) - { - this.interaction.onPointerDown(this.createEvent('touchstart', x, y, identifier, asPointer)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - * @param {boolean} [asPointer] - if it should be a PointerEvent from a touch - */ - touchmove(x, y, identifier, asPointer) - { - this.interaction.onPointerMove(this.createEvent('touchmove', x, y, identifier, asPointer)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - * @param {boolean} [asPointer] - if it should be a PointerEvent from a touch - */ - touchend(x, y, identifier, asPointer) - { - this.interaction.onPointerUp(this.createEvent('touchend', x, y, identifier, asPointer)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - * @param {boolean} [asPointer] - if it should be a PointerEvent from a touch - */ - touchleave(x, y, identifier, asPointer) - { - this.interaction.onPointerOut(this.createEvent('touchleave', x, y, identifier, asPointer)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - */ - pendown(x, y, identifier) - { - this.interaction.onPointerDown(this.createEvent('pointerdown', x, y, identifier, true)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - */ - penmove(x, y, identifier) - { - this.interaction.onPointerMove(this.createEvent('pointermove', x, y, identifier, true)); - } - - /** - * @param {number} x - pointer x position - * @param {number} y - pointer y position - * @param {number} [identifier] - pointer id - */ - penup(x, y, identifier) - { - this.interaction.onPointerUp(this.createEvent('pointerup', x, y, identifier, true)); - } -} - -export { MockPointer }; diff --git a/packages/loaders/README.md b/packages/loaders/README.md deleted file mode 100644 index f619a54eb93..00000000000 --- a/packages/loaders/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# @pixi/loaders - -## Installation - -```bash -npm install @pixi/loaders -``` - -## Usage - -Using the loader directly: - -```js -import { Loader } from '@pixi/loaders'; - -const loader = new Loader(); -loader.add('path/to/file.jpg'); -loader.load(() => {}); -``` - -Using the loader as an Application plugin: - -```js -import { AppLoaderPlugin } from '@pixi/loaders'; -import { Application } from '@pixi/app'; - -Application.registerPlugin(AppLoaderPlugin); - -const app = new Application(); -app.loader.add('path/to/file.jpg'); -app.loader.load(() => {}); -``` diff --git a/packages/loaders/global.d.ts b/packages/loaders/global.d.ts deleted file mode 100644 index a72dfb0e4f4..00000000000 --- a/packages/loaders/global.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -declare namespace GlobalMixins -{ - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface LoaderResource - { - /** - * Texture reference for loading images and other textures. - */ - texture?: Texture; - } - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface IResourceMetadata - { - - } - - /** @deprecated Use LoaderResource instead */ - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface ILoaderResource - { - - } - - interface Application - { - loader: import('@pixi/loaders').Loader; - } - - interface IApplicationOptions - { - sharedLoader?: boolean; - } -} diff --git a/packages/loaders/package.json b/packages/loaders/package.json deleted file mode 100644 index 7df85ce9e72..00000000000 --- a/packages/loaders/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "@pixi/loaders", - "version": "6.3.0", - "main": "dist/cjs/loaders.js", - "module": "dist/esm/loaders.js", - "bundle": "dist/browser/loaders.js", - "description": "Load assets and resources", - "author": "Mat Groves", - "contributors": [ - "Matt Karl " - ], - "homepage": "http://pixijs.com/", - "bugs": "https://github.com/pixijs/pixi.js/issues", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/pixijs/pixi.js.git" - }, - "publishConfig": { - "access": "public" - }, - "files": [ - "lib", - "dist", - "*.d.ts" - ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/utils": "6.3.0" - } -} diff --git a/packages/loaders/src/AppLoaderPlugin.ts b/packages/loaders/src/AppLoaderPlugin.ts deleted file mode 100644 index 9353cbe58b4..00000000000 --- a/packages/loaders/src/AppLoaderPlugin.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Loader } from './Loader'; - -/** - * Application plugin for supporting loader option. Installing the LoaderPlugin - * is not necessary if using **pixi.js** or **pixi.js-legacy**. - * @example - * import {AppLoaderPlugin} from '@pixi/loaders'; - * import {Application} from '@pixi/app'; - * Application.registerPlugin(AppLoaderPlugin); - * @memberof PIXI - */ -export class AppLoaderPlugin -{ - /** - * Loader instance to help with asset loading. - * @memberof PIXI.Application# - * @readonly - */ - public static loader: Loader; - - /** - * Called on application constructor - * - * @private - */ - static init(options?: GlobalMixins.IApplicationOptions): void - { - options = Object.assign({ - sharedLoader: false, - }, options); - - this.loader = options.sharedLoader ? Loader.shared : new Loader(); - } - - /** - * Called when application destroyed - * - * @private - */ - static destroy(): void - { - if (this.loader) - { - this.loader.destroy(); - this.loader = null; - } - } -} diff --git a/packages/loaders/src/Loader.ts b/packages/loaders/src/Loader.ts deleted file mode 100644 index 1e80ed2d4b3..00000000000 --- a/packages/loaders/src/Loader.ts +++ /dev/null @@ -1,795 +0,0 @@ -import { Signal } from './base/Signal'; -import { parseUri } from './base/parseUri'; -import { IResourceMetadata, LoaderResource } from './LoaderResource'; -import { AsyncQueue } from './base/AsyncQueue'; -import { Dict } from '@pixi/utils'; - -// some constants -const MAX_PROGRESS = 100; -const rgxExtractUrlHash = /(#[\w-]+)?$/; - -export type ILoaderMiddleware = (resource: LoaderResource, next: (...args: any[]) => void) => void; - -export interface ILoaderAdd { - (this: Loader, name: string, url: string, callback?: LoaderResource.OnCompleteSignal): Loader; - (this: Loader, name: string, url: string, options?: IAddOptions, callback?: LoaderResource.OnCompleteSignal): Loader; - (this: Loader, url: string, callback?: LoaderResource.OnCompleteSignal): Loader; - (this: Loader, url: string, options?: IAddOptions, callback?: LoaderResource.OnCompleteSignal): Loader; - (this: Loader, options: IAddOptions, callback?: LoaderResource.OnCompleteSignal): Loader; - (this: Loader, resources: (IAddOptions | string)[], callback?: LoaderResource.OnCompleteSignal): Loader; -} - -/** - * Options for a call to `.add()`. - * - * @see Loader#add - * - * @property name - The name of the resource to load, if not passed the url is used. - * @property key - Alias for `name`. - * @property url - The url for this resource, relative to the baseUrl of this loader. - * @property crossOrigin - Is this request cross-origin? Default is to determine automatically. - * @property timeout=0 - A timeout in milliseconds for the load. If the load takes longer - * than this time it is cancelled and the load is considered a failure. If this value is - * set to `0` then there is no explicit timeout. - * @property loadType=LoaderResource.LOAD_TYPE.XHR - How should this resource be loaded? - * @property xhrType=LoaderResource.XHR_RESPONSE_TYPE.DEFAULT - How should the data being - * loaded be interpreted when using XHR? - * @property onComplete - Callback to add an an onComplete signal istener. - * @property callback - Alias for `onComplete`. - * @property metadata - Extra configuration for middleware and the Resource object. - */ -export interface IAddOptions { - name?: string; - key?: string; - url?: string; - crossOrigin?: string | boolean; - timeout?: number; - parentResource?: LoaderResource; - loadType?: LoaderResource.LOAD_TYPE; - xhrType?: LoaderResource.XHR_RESPONSE_TYPE; - onComplete?: LoaderResource.OnCompleteSignal; - callback?: LoaderResource.OnCompleteSignal; - metadata?: IResourceMetadata; -} - -/** - * The new loader, forked from Resource Loader by Chad Engler: https://github.com/englercj/resource-loader - * - * ```js - * const loader = PIXI.Loader.shared; // PixiJS exposes a premade instance for you to use. - * // or - * const loader = new PIXI.Loader(); // You can also create your own if you want - * - * const sprites = {}; - * - * // Chainable `add` to enqueue a resource - * loader.add('bunny', 'data/bunny.png') - * .add('spaceship', 'assets/spritesheet.json'); - * loader.add('scoreFont', 'assets/score.fnt'); - * - * // Chainable `pre` to add a middleware that runs for each resource, *before* loading that resource. - * // This is useful to implement custom caching modules (using filesystem, indexeddb, memory, etc). - * loader.pre(cachingMiddleware); - * - * // Chainable `use` to add a middleware that runs for each resource, *after* loading that resource. - * // This is useful to implement custom parsing modules (like spritesheet parsers, spine parser, etc). - * loader.use(parsingMiddleware); - * - * // The `load` method loads the queue of resources, and calls the passed in callback called once all - * // resources have loaded. - * loader.load((loader, resources) => { - * // resources is an object where the key is the name of the resource loaded and the value is the resource object. - * // They have a couple default properties: - * // - `url`: The URL that the resource was loaded from - * // - `error`: The error that happened when trying to load (if any) - * // - `data`: The raw data that was loaded - * // also may contain other properties based on the middleware that runs. - * sprites.bunny = new PIXI.TilingSprite(resources.bunny.texture); - * sprites.spaceship = new PIXI.TilingSprite(resources.spaceship.texture); - * sprites.scoreFont = new PIXI.TilingSprite(resources.scoreFont.texture); - * }); - * - * // throughout the process multiple signals can be dispatched. - * loader.onProgress.add(() => {}); // called once per loaded/errored file - * loader.onError.add(() => {}); // called once per errored file - * loader.onLoad.add(() => {}); // called once per loaded file - * loader.onComplete.add(() => {}); // called once when the queued resources all load. - * ``` - * - * @memberof PIXI - */ -class Loader -{ - /** - * The base url for all resources loaded by this loader. - */ - baseUrl: string; - - /** - * The progress percent of the loader going through the queue. - */ - progress = 0; - - /** - * Loading state of the loader, true if it is currently loading resources. - */ - loading = false; - - /** - * A querystring to append to every URL added to the loader. - * - * This should be a valid query string *without* the question-mark (`?`). The loader will - * also *not* escape values for you. Make sure to escape your parameters with - * [`encodeURIComponent`](https://mdn.io/encodeURIComponent) before assigning this property. - * - * @example - * const loader = new Loader(); - * - * loader.defaultQueryString = 'user=me&password=secret'; - * - * // This will request 'image.png?user=me&password=secret' - * loader.add('image.png').load(); - * - * loader.reset(); - * - * // This will request 'image.png?v=1&user=me&password=secret' - * loader.add('iamge.png?v=1').load(); - */ - defaultQueryString = ''; - - /** - * The middleware to run before loading each resource. - */ - private _beforeMiddleware: Array = []; - - /** - * The middleware to run after loading each resource. - */ - private _afterMiddleware: Array = []; - - /** - * The tracks the resources we are currently completing parsing for. - */ - private _resourcesParsing: Array = []; - - /** - * The `_loadResource` function bound with this object context. - * - * @param r - The resource to load - * @param d - The dequeue function - */ - private _boundLoadResource = (r: LoaderResource, d: () => void): void => this._loadResource(r, d); - - /** - * The resources waiting to be loaded. - */ - private _queue: AsyncQueue; - - /** - * All the resources for this loader keyed by name. - */ - resources: Dict = {}; - - /** - * Dispatched once per loaded or errored resource. - */ - onProgress: Signal; - - /** - * Dispatched once per errored resource. - */ - onError: Signal; - - /** - * Dispatched once per loaded resource. - */ - onLoad: Signal; - - /** - * Dispatched when the loader begins to process the queue. - */ - onStart: Signal; - - /** - * Dispatched when the queued resources all load. - */ - onComplete: Signal; - - /** - * @param baseUrl - The base url for all resources loaded by this loader. - * @param concurrency - The number of resources to load concurrently. - */ - constructor(baseUrl = '', concurrency = 10) - { - this.baseUrl = baseUrl; - this._beforeMiddleware = []; - this._afterMiddleware = []; - this._resourcesParsing = []; - this._boundLoadResource = (r, d) => this._loadResource(r, d); - this._queue = AsyncQueue.queue(this._boundLoadResource, concurrency); - this._queue.pause(); - this.resources = {}; - this.onProgress = new Signal(); - this.onError = new Signal(); - this.onLoad = new Signal(); - this.onStart = new Signal(); - this.onComplete = new Signal(); - - for (let i = 0; i < Loader._plugins.length; ++i) - { - const plugin = Loader._plugins[i]; - const { pre, use } = plugin; - - if (pre) - { - this.pre(pre); - } - - if (use) - { - this.use(use); - } - } - - this._protected = false; - } - - /** - * Adds a resource (or multiple resources) to the loader queue. - * - * This function can take a wide variety of different parameters. The only thing that is always - * required the url to load. All the following will work: - * - * ```js - * loader - * // normal param syntax - * .add('key', 'http://...', function () {}) - * .add('http://...', function () {}) - * .add('http://...') - * - * // object syntax - * .add({ - * name: 'key2', - * url: 'http://...' - * }, function () {}) - * .add({ - * url: 'http://...' - * }, function () {}) - * .add({ - * name: 'key3', - * url: 'http://...' - * onComplete: function () {} - * }) - * .add({ - * url: 'https://...', - * onComplete: function () {}, - * crossOrigin: true - * }) - * - * // you can also pass an array of objects or urls or both - * .add([ - * { name: 'key4', url: 'http://...', onComplete: function () {} }, - * { url: 'http://...', onComplete: function () {} }, - * 'http://...' - * ]) - * - * // and you can use both params and options - * .add('key', 'http://...', { crossOrigin: true }, function () {}) - * .add('http://...', { crossOrigin: true }, function () {}); - * ``` - */ - add: ILoaderAdd; - - /** - * Same as add, params have strict order - * - * @private - * @param name - The name of the resource to load. - * @param url - The url for this resource, relative to the baseUrl of this loader. - * @param options - The options for the load. - * @param callback - Function to call when this specific resource completes loading. - * @return The loader itself. - */ - protected _add(name: string, url: string, options: IAddOptions, callback?: LoaderResource.OnCompleteSignal): this - { - // if loading already you can only add resources that have a parent. - if (this.loading && (!options || !options.parentResource)) - { - throw new Error('Cannot add resources while the loader is running.'); - } - - // check if resource already exists. - if (this.resources[name]) - { - throw new Error(`Resource named "${name}" already exists.`); - } - - // add base url if this isn't an absolute url - url = this._prepareUrl(url); - - // create the store the resource - this.resources[name] = new LoaderResource(name, url, options); - - if (typeof callback === 'function') - { - this.resources[name].onAfterMiddleware.once(callback); - } - - // if actively loading, make sure to adjust progress chunks for that parent and its children - if (this.loading) - { - const parent = options.parentResource; - const incompleteChildren = []; - - for (let i = 0; i < parent.children.length; ++i) - { - if (!parent.children[i].isComplete) - { - incompleteChildren.push(parent.children[i]); - } - } - - const fullChunk = parent.progressChunk * (incompleteChildren.length + 1); // +1 for parent - const eachChunk = fullChunk / (incompleteChildren.length + 2); // +2 for parent & new child - - parent.children.push(this.resources[name]); - parent.progressChunk = eachChunk; - - for (let i = 0; i < incompleteChildren.length; ++i) - { - incompleteChildren[i].progressChunk = eachChunk; - } - - this.resources[name].progressChunk = eachChunk; - } - - // add the resource to the queue - this._queue.push(this.resources[name]); - - return this; - } - - /* eslint-enable require-jsdoc,valid-jsdoc */ - - /** - * Sets up a middleware function that will run *before* the - * resource is loaded. - * - * @param fn - The middleware function to register. - * @return The loader itself. - */ - pre(fn: ILoaderMiddleware): this - { - this._beforeMiddleware.push(fn); - - return this; - } - - /** - * Sets up a middleware function that will run *after* the - * resource is loaded. - * - * @param fn - The middleware function to register. - * @return The loader itself. - */ - use(fn: ILoaderMiddleware): this - { - this._afterMiddleware.push(fn); - - return this; - } - - /** - * Resets the queue of the loader to prepare for a new load. - * - * @return The loader itself. - */ - reset(): this - { - this.progress = 0; - this.loading = false; - - this._queue.kill(); - this._queue.pause(); - - // abort all resource loads - for (const k in this.resources) - { - const res = this.resources[k]; - - if (res._onLoadBinding) - { - res._onLoadBinding.detach(); - } - - if (res.isLoading) - { - res.abort('loader reset'); - } - } - - this.resources = {}; - - return this; - } - - /** - * Starts loading the queued resources. - * @param cb - Optional callback that will be bound to the `complete` event. - * @return The loader itself. - */ - load(cb?: Loader.OnCompleteSignal): this - { - // register complete callback if they pass one - if (typeof cb === 'function') - { - this.onComplete.once(cb); - } - - // if the queue has already started we are done here - if (this.loading) - { - return this; - } - - if (this._queue.idle()) - { - this._onStart(); - this._onComplete(); - } - else - { - // distribute progress chunks - const numTasks = this._queue._tasks.length; - const chunk = MAX_PROGRESS / numTasks; - - for (let i = 0; i < this._queue._tasks.length; ++i) - { - this._queue._tasks[i].data.progressChunk = chunk; - } - - // notify we are starting - this._onStart(); - - // start loading - this._queue.resume(); - } - - return this; - } - - /** - * The number of resources to load concurrently. - * - * @default 10 - */ - get concurrency(): number - { - return this._queue.concurrency; - } - set concurrency(concurrency: number) - { - this._queue.concurrency = concurrency; - } - - /** - * Prepares a url for usage based on the configuration of this object - * @param url - The url to prepare. - * @return The prepared url. - */ - private _prepareUrl(url: string): string - { - const parsedUrl = parseUri(url, { strictMode: true }); - let result; - - // absolute url, just use it as is. - if (parsedUrl.protocol || !parsedUrl.path || url.indexOf('//') === 0) - { - result = url; - } - // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween - else if (this.baseUrl.length - && this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 - && url.charAt(0) !== '/' - ) - { - result = `${this.baseUrl}/${url}`; - } - else - { - result = this.baseUrl + url; - } - - // if we need to add a default querystring, there is a bit more work - if (this.defaultQueryString) - { - const hash = rgxExtractUrlHash.exec(result)[0]; - - result = result.slice(0, result.length - hash.length); - - if (result.indexOf('?') !== -1) - { - result += `&${this.defaultQueryString}`; - } - else - { - result += `?${this.defaultQueryString}`; - } - - result += hash; - } - - return result; - } - - /** - * Loads a single resource. - * - * @param resource - The resource to load. - * @param dequeue - The function to call when we need to dequeue this item. - */ - private _loadResource(resource: LoaderResource, dequeue: () => void): void - { - resource._dequeue = dequeue; - - // run before middleware - AsyncQueue.eachSeries( - this._beforeMiddleware, - (fn: any, next: (...args: any) => void) => - { - fn.call(this, resource, () => - { - // if the before middleware marks the resource as complete, - // break and don't process any more before middleware - next(resource.isComplete ? {} : null); - }); - }, - () => - { - if (resource.isComplete) - { - this._onLoad(resource); - } - else - { - resource._onLoadBinding = resource.onComplete.once(this._onLoad, this); - resource.load(); - } - }, - true - ); - } - - /** - * Called once loading has started. - */ - private _onStart(): void - { - this.progress = 0; - this.loading = true; - this.onStart.dispatch(this); - } - - /** - * Called once each resource has loaded. - */ - private _onComplete(): void - { - this.progress = MAX_PROGRESS; - this.loading = false; - this.onComplete.dispatch(this, this.resources); - } - - /** - * Called each time a resources is loaded. - * @param resource - The resource that was loaded - */ - private _onLoad(resource: LoaderResource): void - { - resource._onLoadBinding = null; - - // remove this resource from the async queue, and add it to our list of resources that are being parsed - this._resourcesParsing.push(resource); - resource._dequeue(); - - // run all the after middleware for this resource - AsyncQueue.eachSeries( - this._afterMiddleware, - (fn: any, next: any) => - { - fn.call(this, resource, next); - }, - () => - { - resource.onAfterMiddleware.dispatch(resource); - - this.progress = Math.min(MAX_PROGRESS, this.progress + resource.progressChunk); - this.onProgress.dispatch(this, resource); - - if (resource.error) - { - this.onError.dispatch(resource.error, this, resource); - } - else - { - this.onLoad.dispatch(this, resource); - } - - this._resourcesParsing.splice(this._resourcesParsing.indexOf(resource), 1); - - // do completion check - if (this._queue.idle() && this._resourcesParsing.length === 0) - { - this._onComplete(); - } - }, - true - ); - } - - private static _plugins: Array = []; - private static _shared: Loader; - /** - * If this loader cannot be destroyed. - * @default false - */ - private _protected: boolean; - - /** - * Destroy the loader, removes references. - */ - public destroy(): void - { - if (!this._protected) - { - this.reset(); - } - } - - /** - * A premade instance of the loader that can be used to load resources. - */ - public static get shared(): Loader - { - let shared = Loader._shared; - - if (!shared) - { - shared = new Loader(); - shared._protected = true; - Loader._shared = shared; - } - - return shared; - } - - /** - * Adds a Loader plugin for the global shared loader and all - * new Loader instances created. - * - * @param plugin - The plugin to add - * @return Reference to PIXI.Loader for chaining - */ - public static registerPlugin(plugin: ILoaderPlugin): typeof Loader - { - Loader._plugins.push(plugin); - - if (plugin.add) - { - plugin.add(); - } - - return Loader; - } -} - -Loader.prototype.add = function add(this: Loader, name: any, url?: any, options?: any, callback?: any): Loader -{ - // special case of an array of objects or urls - if (Array.isArray(name)) - { - for (let i = 0; i < name.length; ++i) - { - this.add((name as any)[i]); - } - - return this; - } - - // if an object is passed instead of params - if (typeof name === 'object') - { - options = name; - callback = (url as any) || options.callback || options.onComplete; - url = options.url; - name = options.name || options.key || options.url; - } - - // case where no name is passed shift all args over by one. - if (typeof url !== 'string') - { - callback = options as any; - options = url; - url = name; - } - - // now that we shifted make sure we have a proper url. - if (typeof url !== 'string') - { - throw new Error('No url passed to add resource to loader.'); - } - - // options are optional so people might pass a function and no options - if (typeof options === 'function') - { - callback = options; - options = null; - } - - return this._add(name, url, options, callback); -}; - -// eslint-disable-next-line @typescript-eslint/no-namespace -namespace Loader -{ - /** - * When the resource starts to load. - * @param resource - The resource that the event happened on. - */ - export type OnStartSignal = (loader: Loader) => void; - /** - * When the progress changes the loader and resource are dispatched. - * @param loader - The loader the progress is advancing on. - * @param resource - The resource that has completed or failed to cause the progress to advance. - */ - export type OnProgressSignal = (loader: Loader, resource: LoaderResource) => void; - /** - * When a load completes without error the loader and resource are dispatched. - * @param loader - The loader that has started loading resources. - * @param resource - The resource that has completed. - */ - export type OnLoadSignal = (loader: Loader, resource: LoaderResource) => void; - /** - * When the loader starts loading resources it dispatches this callback. - * @param loader - The loader that has started loading resources. - */ - export type OnCompleteSignal = (loader: Loader, resources: Dict) => void; - /** - * When an error occurs the loader and resource are dispatched. - * @param loader - The loader the error happened in. - * @param resource - The resource that caused the error. - */ - export type OnErrorSignal = (error: Error, loader: Loader, resource: LoaderResource) => void; -} - -export { Loader }; - -/** - * Plugin to be installed for handling specific Loader resources. - * - * @property add - Function to call immediate after registering plugin. - * @property pre - Middleware function to run before load, the - * arguments for this are `(resource, next)` - * @property use - Middleware function to run after load, the - * arguments for this are `(resource, next)` - */ -export interface ILoaderPlugin { - /** - * Function to call immediate after registering plugin. - */ - add?(): void; - - /** - * Middleware function to run before load - * @param resource - resource - * @param next - next middleware - */ - pre?(resource: LoaderResource, next: (...args: any[]) => void): void; - - /** - * Middleware function to run after load - * @param resource - resource - * @param next - next middleware - */ - use?(resource: LoaderResource, next: (...args: any[]) => void): void; -} diff --git a/packages/loaders/src/LoaderResource.ts b/packages/loaders/src/LoaderResource.ts deleted file mode 100644 index 42b050f71bc..00000000000 --- a/packages/loaders/src/LoaderResource.ts +++ /dev/null @@ -1,1415 +0,0 @@ -import { Dict } from '@pixi/utils'; -import { Signal } from './base/Signal'; -import { parseUri } from './base/parseUri'; -import type { IBaseTextureOptions, Texture } from '@pixi/core'; - -// tests if CORS is supported in XHR, if not we need to use XDR -const useXdr = !!((globalThis as any).XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))); -let tempAnchor: any = null; - -// some status constants -const STATUS_NONE = 0; -const STATUS_OK = 200; -const STATUS_EMPTY = 204; -const STATUS_IE_BUG_EMPTY = 1223; -const STATUS_TYPE_OK = 2; - -// noop -function _noop(): void { /* empty */ } - -/** - * Quick helper to set a value on one of the extension maps. Ensures there is no - * dot at the start of the extension. - * - * @ignore - * @param map - The map to set on. - * @param extname - The extension (or key) to set. - * @param val - The value to set. - */ -function setExtMap(map: Dict, extname: string, val: number) -{ - if (extname && extname.indexOf('.') === 0) - { - extname = extname.substring(1); - } - - if (!extname) - { - return; - } - - map[extname] = val; -} - -/** - * Quick helper to get string xhr type. - * - * @ignore - * @param xhr - The request to check. - * @return The type. - */ -function reqType(xhr: XMLHttpRequest) -{ - return xhr.toString().replace('object ', ''); -} - -/** - * Metadata for loader resource. It is very messy way to pass options for loader middlewares - * - * Can be extended in `GlobalMixins.IResourceMetadata` - * - * @memberof PIXI - */ -export interface IResourceMetadata extends GlobalMixins.IResourceMetadata, IBaseTextureOptions -{ - /** - * The element to use for loading, instead of creating one. - */ - loadElement?: HTMLImageElement | HTMLAudioElement | HTMLVideoElement; - /** - * Skips adding source(s) to the load element. This - * is useful if you want to pass in a `loadElement` that you already added load sources to. - */ - skipSource?: boolean; - /** - * The mime type to use for the source element - * of a video/audio elment. If the urls are an array, you can pass this as an array as well - * where each index is the mime type to use for the corresponding url index. - */ - mimeType?: string | string[]; - - /** - * Used by BitmapFonts, Spritesheet and CompressedTextures as the options to used for - * metadata when loading the child image. - */ - imageMetadata?: IResourceMetadata; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface LoaderResource extends GlobalMixins.LoaderResource, GlobalMixins.ILoaderResource {} - -/** - * Manages the state and loading of a resource and all child resources. - * - * Can be extended in `GlobalMixins.LoaderResource`. - * - * @memberof PIXI - */ -class LoaderResource -{ - /** - * Texture reference for loading images and other textures. - * @type {PIXI.Texture} - */ - texture?: Texture; - - /** - * used by parsing middleware - */ - blob?: Blob; - - /** - * The name of this resource. - * - * @readonly - * @type {string} - */ - readonly name: string; - /** - * The url used to load this resource. - * - * @readonly - * @type {string} - */ - readonly url: string; - /** - * The extension used to load this resource. - * - * @readonly - * @type {string} - */ - readonly extension: string; - /** - * The data that was loaded by the resource. - */ - data: any; - /** - * Is this request cross-origin? If unset, determined automatically. - */ - crossOrigin: string | boolean; - /** - * A timeout in milliseconds for the load. If the load takes longer than this time - * it is cancelled and the load is considered a failure. If this value is set to `0` - * then there is no explicit timeout. - * - * @type {number} - */ - timeout: number; - /** - * The method of loading to use for this resource. - * - * @type {PIXI.LoaderResource.LOAD_TYPE} - */ - loadType: LoaderResource.LOAD_TYPE; - /** - * The type used to load the resource via XHR. If unset, determined automatically. - * - * @member {string} - */ - xhrType: string; - - /** - * Extra info for middleware, and controlling specifics about how the resource loads. - * - * Note that if you pass in a `loadElement`, the Resource class takes ownership of it. - * Meaning it will modify it as it sees fit. - * - * @type {PIXI.IResourceMetadata} - */ - metadata: IResourceMetadata; - /** - * The error that occurred while loading (if any). - * - * @readonly - * @member {Error} - */ - error: Error; - /** - * The XHR object that was used to load this resource. This is only set - * when `loadType` is `LoaderResource.LOAD_TYPE.XHR`. - * - * @readonly - */ - xhr: XMLHttpRequest; - - private xdr: any; - /** - * The child resources this resource owns. - * - * @type {PIXI.LoaderResource[]} - */ - readonly children: LoaderResource[]; - /** - * The resource type. - * - * @readonly - * @type {PIXI.LoaderResource.TYPE} - */ - type: LoaderResource.TYPE; - /** - * The progress chunk owned by this resource. - * - * @readonly - * @member {number} - */ - progressChunk: number; - /** - * Dispatched when the resource beings to load. - * - * The callback looks like {@link LoaderResource.OnStartSignal}. - * - * @type {PIXI.Signal} - */ - onStart: Signal; - /** - * Dispatched each time progress of this resource load updates. - * Not all resources types and loader systems can support this event - * so sometimes it may not be available. If the resource - * is being loaded on a modern browser, using XHR, and the remote server - * properly sets Content-Length headers, then this will be available. - * - * The callback looks like {@link LoaderResource.OnProgressSignal}. - * - * @type {PIXI.Signal} - */ - onProgress: Signal; - /** - * Dispatched once this resource has loaded, if there was an error it will - * be in the `error` property. - * - * The callback looks like {@link LoaderResource.OnCompleteSignal}. - * - * @type {PIXI.Signal} - */ - onComplete: Signal; - /** - * Dispatched after this resource has had all the *after* middleware run on it. - * - * The callback looks like {@link LoaderResource.OnCompleteSignal}. - * - * @type {PIXI.Signal} - */ - onAfterMiddleware: Signal; - - /** - * The state flags of this resource. - * - * @private - * @member {number} - */ - private _flags: number; - - /** - * The `dequeue` method that will be used a storage place for the async queue dequeue method - * used privately by the loader. - * - * @private - * @member {function} - */ - _dequeue: any = _noop; - - /** - * Used a storage place for the on load binding used privately by the loader. - * - * @private - * @member {function} - */ - _onLoadBinding: any = null; - - /** - * The timer for element loads to check if they timeout. - * - * @private - */ - private _elementTimer = 0; - - /** - * The `complete` function bound to this resource's context. - * - * @private - * @type {function} - */ - private _boundComplete: any = null; - - /** - * The `_onError` function bound to this resource's context. - * - * @private - * @type {function} - */ - private _boundOnError: any = null; - - /** - * The `_onProgress` function bound to this resource's context. - * - * @private - * @type {function} - */ - private _boundOnProgress: any = null; - - /** - * The `_onTimeout` function bound to this resource's context. - * - * @private - * @type {function} - */ - private _boundOnTimeout: any = null; - - private _boundXhrOnError: any = null; - private _boundXhrOnTimeout: any = null; - private _boundXhrOnAbort: any = null; - private _boundXhrOnLoad: any = null; - - /** - * Sets the load type to be used for a specific extension. - * - * @static - * @param {string} extname - The extension to set the type for, e.g. "png" or "fnt" - * @param {PIXI.LoaderResource.LOAD_TYPE} loadType - The load type to set it to. - */ - static setExtensionLoadType(extname: string, loadType: LoaderResource.LOAD_TYPE): void - { - setExtMap(LoaderResource._loadTypeMap, extname, loadType); - } - /** - * Sets the load type to be used for a specific extension. - * - * @static - * @param {string} extname - The extension to set the type for, e.g. "png" or "fnt" - * @param {PIXI.LoaderResource.XHR_RESPONSE_TYPE} xhrType - The xhr type to set it to. - */ - static setExtensionXhrType(extname: string, xhrType: LoaderResource.XHR_RESPONSE_TYPE): void - { - setExtMap(LoaderResource._xhrTypeMap, extname, xhrType as any); - } - - /** - * @param {string} name - The name of the resource to load. - * @param {string|string[]} url - The url for this resource, for audio/video loads you can pass - * an array of sources. - * @param {object} [options] - The options for the load. - * @param {string|boolean} [options.crossOrigin] - Is this request cross-origin? Default is to - * determine automatically. - * @param {number} [options.timeout=0] - A timeout in milliseconds for the load. If the load takes - * longer than this time it is cancelled and the load is considered a failure. If this value is - * set to `0` then there is no explicit timeout. - * @param {PIXI.LoaderResource.LOAD_TYPE} [options.loadType=LOAD_TYPE.XHR] - How should this resource - * be loaded? - * @param {PIXI.LoaderResource.XHR_RESPONSE_TYPE} [options.xhrType=XHR_RESPONSE_TYPE.DEFAULT] - How - * should the data being loaded be interpreted when using XHR? - * @param {PIXI.LoaderResource.IMetadata} [options.metadata] - Extra configuration for middleware - * and the Resource object. - */ - constructor(name: string, url: string | string[], options?: { - crossOrigin?: string | boolean; - timeout?: number; - loadType?: LoaderResource.LOAD_TYPE; - xhrType?: LoaderResource.XHR_RESPONSE_TYPE; - metadata?: IResourceMetadata; - }) - { - if (typeof name !== 'string' || typeof url !== 'string') - { - throw new Error('Both name and url are required for constructing a resource.'); - } - - options = options || {}; - - this._flags = 0; - - // set data url flag, needs to be set early for some _determineX checks to work. - this._setFlag(LoaderResource.STATUS_FLAGS.DATA_URL, url.indexOf('data:') === 0); - - this.name = name; - - this.url = url; - - this.extension = this._getExtension(); - - this.data = null; - - this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin; - - this.timeout = options.timeout || 0; - - this.loadType = options.loadType || this._determineLoadType(); - - // The type used to load the resource via XHR. If unset, determined automatically. - this.xhrType = options.xhrType; - - // Extra info for middleware, and controlling specifics about how the resource loads. - // Note that if you pass in a `loadElement`, the Resource class takes ownership of it. - // Meaning it will modify it as it sees fit. - this.metadata = options.metadata || {}; - - // The error that occurred while loading (if any). - this.error = null; - - // The XHR object that was used to load this resource. This is only set - // when `loadType` is `LoaderResource.LOAD_TYPE.XHR`. - this.xhr = null; - - // The child resources this resource owns. - this.children = []; - - // The resource type. - this.type = LoaderResource.TYPE.UNKNOWN; - - // The progress chunk owned by this resource. - this.progressChunk = 0; - - // The `dequeue` method that will be used a storage place for the async queue dequeue method - // used privately by the loader. - this._dequeue = _noop; - - // Used a storage place for the on load binding used privately by the loader. - this._onLoadBinding = null; - - // The timer for element loads to check if they timeout. - this._elementTimer = 0; - - this._boundComplete = this.complete.bind(this); - this._boundOnError = this._onError.bind(this); - this._boundOnProgress = this._onProgress.bind(this); - this._boundOnTimeout = this._onTimeout.bind(this); - - // xhr callbacks - this._boundXhrOnError = this._xhrOnError.bind(this); - this._boundXhrOnTimeout = this._xhrOnTimeout.bind(this); - this._boundXhrOnAbort = this._xhrOnAbort.bind(this); - this._boundXhrOnLoad = this._xhrOnLoad.bind(this); - - // Dispatched when the resource beings to load. - this.onStart = new Signal(); - - // Dispatched each time progress of this resource load updates. - // Not all resources types and loader systems can support this event - // so sometimes it may not be available. If the resource - // is being loaded on a modern browser, using XHR, and the remote server - // properly sets Content-Length headers, then this will be available. - this.onProgress = new Signal(); - - // Dispatched once this resource has loaded, if there was an error it will - // be in the `error` property. - this.onComplete = new Signal(); - - // Dispatched after this resource has had all the *after* middleware run on it. - this.onAfterMiddleware = new Signal(); - } - - /** - * When the resource starts to load. - * - * @memberof PIXI.LoaderResource - * @callback OnStartSignal - * @param {Resource} resource - The resource that the event happened on. - */ - - /** - * When the resource reports loading progress. - * - * @memberof PIXI.LoaderResource - * @callback OnProgressSignal - * @param {Resource} resource - The resource that the event happened on. - * @param {number} percentage - The progress of the load in the range [0, 1]. - */ - - /** - * When the resource finishes loading. - * - * @memberof PIXI.LoaderResource - * @callback OnCompleteSignal - * @param {Resource} resource - The resource that the event happened on. - */ - - /** - * @memberof PIXI.LoaderResource - * @typedef {object} IMetadata - * @property {HTMLImageElement|HTMLAudioElement|HTMLVideoElement} [loadElement=null] - The - * element to use for loading, instead of creating one. - * @property {boolean} [skipSource=false] - Skips adding source(s) to the load element. This - * is useful if you want to pass in a `loadElement` that you already added load sources to. - * @property {string|string[]} [mimeType] - The mime type to use for the source element - * of a video/audio elment. If the urls are an array, you can pass this as an array as well - * where each index is the mime type to use for the corresponding url index. - */ - - /** - * Stores whether or not this url is a data url. - * - * @readonly - * @member {boolean} - */ - get isDataUrl(): boolean - { - return this._hasFlag(LoaderResource.STATUS_FLAGS.DATA_URL); - } - - /** - * Describes if this resource has finished loading. Is true when the resource has completely - * loaded. - * - * @readonly - * @member {boolean} - */ - get isComplete(): boolean - { - return this._hasFlag(LoaderResource.STATUS_FLAGS.COMPLETE); - } - - /** - * Describes if this resource is currently loading. Is true when the resource starts loading, - * and is false again when complete. - * - * @readonly - * @member {boolean} - */ - get isLoading(): boolean - { - return this._hasFlag(LoaderResource.STATUS_FLAGS.LOADING); - } - - /** - * Marks the resource as complete. - * - */ - complete(): void - { - this._clearEvents(); - this._finish(); - } - - /** - * Aborts the loading of this resource, with an optional message. - * - * @param {string} message - The message to use for the error - */ - abort(message: string): void - { - // abort can be called multiple times, ignore subsequent calls. - if (this.error) - { - return; - } - - // store error - this.error = new Error(message); - - // clear events before calling aborts - this._clearEvents(); - - // abort the actual loading - if (this.xhr) - { - this.xhr.abort(); - } - else if (this.xdr) - { - this.xdr.abort(); - } - else if (this.data) - { - // single source - if (this.data.src) - { - this.data.src = LoaderResource.EMPTY_GIF; - } - // multi-source - else - { - while (this.data.firstChild) - { - this.data.removeChild(this.data.firstChild); - } - } - } - - // done now. - this._finish(); - } - - /** - * Kicks off loading of this resource. This method is asynchronous. - * - * @param {PIXI.LoaderResource.OnCompleteSignal} [cb] - Optional callback to call once the resource is loaded. - */ - load(cb?: LoaderResource.OnCompleteSignal): void - { - if (this.isLoading) - { - return; - } - - if (this.isComplete) - { - if (cb) - { - setTimeout(() => cb(this), 1); - } - - return; - } - else if (cb) - { - this.onComplete.once(cb); - } - - this._setFlag(LoaderResource.STATUS_FLAGS.LOADING, true); - - this.onStart.dispatch(this); - - // if unset, determine the value - if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') - { - this.crossOrigin = this._determineCrossOrigin(this.url); - } - - switch (this.loadType) - { - case LoaderResource.LOAD_TYPE.IMAGE: - this.type = LoaderResource.TYPE.IMAGE; - this._loadElement('image'); - break; - - case LoaderResource.LOAD_TYPE.AUDIO: - this.type = LoaderResource.TYPE.AUDIO; - this._loadSourceElement('audio'); - break; - - case LoaderResource.LOAD_TYPE.VIDEO: - this.type = LoaderResource.TYPE.VIDEO; - this._loadSourceElement('video'); - break; - - case LoaderResource.LOAD_TYPE.XHR: - /* falls through */ - default: - if (useXdr && this.crossOrigin) - { - this._loadXdr(); - } - else - { - this._loadXhr(); - } - break; - } - } - - /** - * Checks if the flag is set. - * - * @param flag - The flag to check. - * @return True if the flag is set. - */ - private _hasFlag(flag: number): boolean - { - return (this._flags & flag) !== 0; - } - - /** - * (Un)Sets the flag. - * - * @param flag - The flag to (un)set. - * @param value - Whether to set or (un)set the flag. - */ - private _setFlag(flag: number, value: boolean): void - { - this._flags = value ? (this._flags | flag) : (this._flags & ~flag); - } - - /** - * Clears all the events from the underlying loading source. - */ - private _clearEvents(): void - { - clearTimeout(this._elementTimer); - - if (this.data && this.data.removeEventListener) - { - this.data.removeEventListener('error', this._boundOnError, false); - this.data.removeEventListener('load', this._boundComplete, false); - this.data.removeEventListener('progress', this._boundOnProgress, false); - this.data.removeEventListener('canplaythrough', this._boundComplete, false); - } - - if (this.xhr) - { - if (this.xhr.removeEventListener) - { - this.xhr.removeEventListener('error', this._boundXhrOnError, false); - this.xhr.removeEventListener('timeout', this._boundXhrOnTimeout, false); - this.xhr.removeEventListener('abort', this._boundXhrOnAbort, false); - this.xhr.removeEventListener('progress', this._boundOnProgress, false); - this.xhr.removeEventListener('load', this._boundXhrOnLoad, false); - } - else - { - this.xhr.onerror = null; - this.xhr.ontimeout = null; - this.xhr.onprogress = null; - this.xhr.onload = null; - } - } - } - - /** - * Finalizes the load. - */ - private _finish(): void - { - if (this.isComplete) - { - throw new Error('Complete called again for an already completed resource.'); - } - - this._setFlag(LoaderResource.STATUS_FLAGS.COMPLETE, true); - this._setFlag(LoaderResource.STATUS_FLAGS.LOADING, false); - - this.onComplete.dispatch(this); - } - - /** - * Loads this resources using an element that has a single source, - * like an HTMLImageElement. - * @private - * @param type - The type of element to use. - */ - _loadElement(type: string): void - { - if (this.metadata.loadElement) - { - this.data = this.metadata.loadElement; - } - else if (type === 'image' && typeof globalThis.Image !== 'undefined') - { - this.data = new Image(); - } - else - { - this.data = document.createElement(type); - } - - if (this.crossOrigin) - { - this.data.crossOrigin = this.crossOrigin; - } - - if (!this.metadata.skipSource) - { - this.data.src = this.url; - } - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); - - if (this.timeout) - { - this._elementTimer = setTimeout(this._boundOnTimeout, this.timeout) as any; - } - } - - /** - * Loads this resources using an element that has multiple sources, - * like an HTMLAudioElement or HTMLVideoElement. - * @param type - The type of element to use. - */ - private _loadSourceElement(type: string): void - { - if (this.metadata.loadElement) - { - this.data = this.metadata.loadElement; - } - else if (type === 'audio' && typeof globalThis.Audio !== 'undefined') - { - this.data = new Audio(); - } - else - { - this.data = document.createElement(type); - } - - if (this.data === null) - { - this.abort(`Unsupported element: ${type}`); - - return; - } - - if (this.crossOrigin) - { - this.data.crossOrigin = this.crossOrigin; - } - - if (!this.metadata.skipSource) - { - // support for CocoonJS Canvas+ runtime, lacks document.createElement('source') - if ((navigator as any).isCocoonJS) - { - this.data.src = Array.isArray(this.url) ? this.url[0] : this.url; - } - else if (Array.isArray(this.url)) - { - const mimeTypes = this.metadata.mimeType; - - for (let i = 0; i < this.url.length; ++i) - { - this.data.appendChild( - this._createSource(type, this.url[i], Array.isArray(mimeTypes) ? mimeTypes[i] : mimeTypes) - ); - } - } - else - { - const mimeTypes = this.metadata.mimeType; - - this.data.appendChild( - this._createSource(type, this.url, Array.isArray(mimeTypes) ? mimeTypes[0] : mimeTypes) - ); - } - } - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); - this.data.addEventListener('canplaythrough', this._boundComplete, false); - - this.data.load(); - - if (this.timeout) - { - this._elementTimer = setTimeout(this._boundOnTimeout, this.timeout) as any; - } - } - - /** - * Loads this resources using an XMLHttpRequest. - */ - private _loadXhr(): void - { - // if unset, determine the value - if (typeof this.xhrType !== 'string') - { - this.xhrType = this._determineXhrType(); - } - - const xhr = this.xhr = new XMLHttpRequest(); - - // send credentials when crossOrigin with credentials requested - if (this.crossOrigin === 'use-credentials') - { - xhr.withCredentials = true; - } - - // set the request type and url - xhr.open('GET', this.url, true); - - xhr.timeout = this.timeout; - - // load json as text and parse it ourselves. We do this because some browsers - // *cough* safari *cough* can't deal with it. - if (this.xhrType === LoaderResource.XHR_RESPONSE_TYPE.JSON - || this.xhrType === LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT) - { - xhr.responseType = LoaderResource.XHR_RESPONSE_TYPE.TEXT; - } - else - { - xhr.responseType = this.xhrType as any; - } - - xhr.addEventListener('error', this._boundXhrOnError, false); - xhr.addEventListener('timeout', this._boundXhrOnTimeout, false); - xhr.addEventListener('abort', this._boundXhrOnAbort, false); - xhr.addEventListener('progress', this._boundOnProgress, false); - xhr.addEventListener('load', this._boundXhrOnLoad, false); - - xhr.send(); - } - - /** - * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross). - */ - private _loadXdr(): void - { - // if unset, determine the value - if (typeof this.xhrType !== 'string') - { - this.xhrType = this._determineXhrType(); - } - - const xdr = this.xhr = new (globalThis as any).XDomainRequest(); // eslint-disable-line no-undef - - // XDomainRequest has a few quirks. Occasionally it will abort requests - // A way to avoid this is to make sure ALL callbacks are set even if not used - // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - xdr.timeout = this.timeout || 5000; // XDR needs a timeout value or it breaks in IE9 - - xdr.onerror = this._boundXhrOnError; - xdr.ontimeout = this._boundXhrOnTimeout; - xdr.onprogress = this._boundOnProgress; - xdr.onload = this._boundXhrOnLoad; - - xdr.open('GET', this.url, true); - - // Note: The xdr.send() call is wrapped in a timeout to prevent an - // issue with the interface where some requests are lost if multiple - // XDomainRequests are being sent at the same time. - // Some info here: https://github.com/photonstorm/phaser/issues/1248 - setTimeout(() => xdr.send(), 1); - } - - /** - * Creates a source used in loading via an element. - * @param type - The element type (video or audio). - * @param url - The source URL to load from. - * @param [mime] - The mime type of the video - * @return The source element. - */ - private _createSource(type: string, url: string, mime: string): HTMLSourceElement - { - if (!mime) - { - mime = `${type}/${this._getExtension(url)}`; - } - - const source = document.createElement('source'); - - source.src = url; - source.type = mime; - - return source; - } - - /** - * Called if a load errors out. - * - * @param event - The error event from the element that emits it. - */ - private _onError(event: Event): void - { - this.abort(`Failed to load element using: ${(event.target as any).nodeName}`); - } - - /** - * Called if a load progress event fires for an element or xhr/xdr. - * @param event - Progress event. - */ - private _onProgress(event: ProgressEvent): void - { - if (event && event.lengthComputable) - { - this.onProgress.dispatch(this, event.loaded / event.total); - } - } - - /** - * Called if a timeout event fires for an element. - */ - private _onTimeout(): void - { - this.abort(`Load timed out.`); - } - - /** - * Called if an error event fires for xhr/xdr. - */ - private _xhrOnError(): void - { - const xhr = this.xhr; - - this.abort(`${reqType(xhr)} Request failed. Status: ${xhr.status}, text: "${xhr.statusText}"`); - } - - /** - * Called if an error event fires for xhr/xdr. - */ - private _xhrOnTimeout(): void - { - const xhr = this.xhr; - - this.abort(`${reqType(xhr)} Request timed out.`); - } - - /** - * Called if an abort event fires for xhr/xdr. - */ - private _xhrOnAbort(): void - { - const xhr = this.xhr; - - this.abort(`${reqType(xhr)} Request was aborted by the user.`); - } - - /** - * Called when data successfully loads from an xhr/xdr request. - */ - private _xhrOnLoad(): void - { - const xhr = this.xhr; - let text = ''; - let status = typeof xhr.status === 'undefined' ? STATUS_OK : xhr.status; // XDR has no `.status`, assume 200. - - // responseText is accessible only if responseType is '' or 'text' and on older browsers - if (xhr.responseType === '' || xhr.responseType === 'text' || typeof xhr.responseType === 'undefined') - { - text = xhr.responseText; - } - - // status can be 0 when using the `file://` protocol so we also check if a response is set. - // If it has a response, we assume 200; otherwise a 0 status code with no contents is an aborted request. - if (status === STATUS_NONE && (text.length > 0 || xhr.responseType === LoaderResource.XHR_RESPONSE_TYPE.BUFFER)) - { - status = STATUS_OK; - } - // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request - else if (status === STATUS_IE_BUG_EMPTY) - { - status = STATUS_EMPTY; - } - - const statusType = (status / 100) | 0; - - if (statusType === STATUS_TYPE_OK) - { - // if text, just return it - if (this.xhrType === LoaderResource.XHR_RESPONSE_TYPE.TEXT) - { - this.data = text; - this.type = LoaderResource.TYPE.TEXT; - } - // if json, parse into json object - else if (this.xhrType === LoaderResource.XHR_RESPONSE_TYPE.JSON) - { - try - { - this.data = JSON.parse(text); - this.type = LoaderResource.TYPE.JSON; - } - catch (e) - { - this.abort(`Error trying to parse loaded json: ${e}`); - - return; - } - } - // if xml, parse into an xml document or div element - else if (this.xhrType === LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT) - { - try - { - if (globalThis.DOMParser) - { - const domparser = new DOMParser(); - - this.data = domparser.parseFromString(text, 'text/xml'); - } - else - { - const div = document.createElement('div'); - - div.innerHTML = text; - - this.data = div; - } - - this.type = LoaderResource.TYPE.XML; - } - catch (e) - { - this.abort(`Error trying to parse loaded xml: ${e}`); - - return; - } - } - // other types just return the response - else - { - this.data = xhr.response || text; - } - } - else - { - this.abort(`[${xhr.status}] ${xhr.statusText}: ${xhr.responseURL}`); - - return; - } - - this.complete(); - } - - /** - * Sets the `crossOrigin` property for this resource based on if the url - * for this resource is cross-origin. If crossOrigin was manually set, this - * function does nothing. - * @private - * @param url - The url to test. - * @param [loc=globalThis.location] - The location object to test against. - * @return The crossOrigin value to use (or empty string for none). - */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - _determineCrossOrigin(url: string, loc?: any): string - { - // data: and javascript: urls are considered same-origin - if (url.indexOf('data:') === 0) - { - return ''; - } - - // A sandboxed iframe without the 'allow-same-origin' attribute will have a special - // origin designed not to match globalThis.location.origin, and will always require - // crossOrigin requests regardless of whether the location matches. - if (globalThis.origin !== globalThis.location.origin) - { - return 'anonymous'; - } - - // default is globalThis.location - loc = loc || globalThis.location; - - if (!tempAnchor) - { - tempAnchor = document.createElement('a'); - } - - // let the browser determine the full href for the url of this resource and then - // parse with the node url lib, we can't use the properties of the anchor element - // because they don't work in IE9 :( - tempAnchor.href = url; - const parsedUrl = parseUri(tempAnchor.href, { strictMode: true }); - - const samePort = (!parsedUrl.port && loc.port === '') || (parsedUrl.port === loc.port); - const protocol = parsedUrl.protocol ? `${parsedUrl.protocol}:` : ''; - - // if cross origin - if (parsedUrl.host !== loc.hostname || !samePort || protocol !== loc.protocol) - { - return 'anonymous'; - } - - return ''; - } - - /** - * Determines the responseType of an XHR request based on the extension of the - * resource being loaded. - * - * @private - * @return {PIXI.LoaderResource.XHR_RESPONSE_TYPE} The responseType to use. - */ - private _determineXhrType(): LoaderResource.XHR_RESPONSE_TYPE - { - return LoaderResource._xhrTypeMap[this.extension] || LoaderResource.XHR_RESPONSE_TYPE.TEXT; - } - - /** - * Determines the loadType of a resource based on the extension of the - * resource being loaded. - * - * @private - * @return {PIXI.LoaderResource.LOAD_TYPE} The loadType to use. - */ - private _determineLoadType(): LoaderResource.LOAD_TYPE - { - return LoaderResource._loadTypeMap[this.extension] || LoaderResource.LOAD_TYPE.XHR; - } - - /** - * Extracts the extension (sans '.') of the file being loaded by the resource. - * - * @param [url] - url to parse, `this.url` by default. - * @return The extension. - */ - private _getExtension(url = this.url): string - { - let ext = ''; - - if (this.isDataUrl) - { - const slashIndex = url.indexOf('/'); - - ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex)); - } - else - { - const queryStart = url.indexOf('?'); - const hashStart = url.indexOf('#'); - const index = Math.min( - queryStart > -1 ? queryStart : url.length, - hashStart > -1 ? hashStart : url.length - ); - - url = url.substring(0, index); - ext = url.substring(url.lastIndexOf('.') + 1); - } - - return ext.toLowerCase(); - } - - /** - * Determines the mime type of an XHR request based on the responseType of - * resource being loaded. - * - * @param type - The type to get a mime type for. - * @private - * @return The mime type to use. - */ - _getMimeFromXhrType(type: LoaderResource.XHR_RESPONSE_TYPE): string - { - switch (type) - { - case LoaderResource.XHR_RESPONSE_TYPE.BUFFER: - return 'application/octet-binary'; - - case LoaderResource.XHR_RESPONSE_TYPE.BLOB: - return 'application/blob'; - - case LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT: - return 'application/xml'; - - case LoaderResource.XHR_RESPONSE_TYPE.JSON: - return 'application/json'; - - case LoaderResource.XHR_RESPONSE_TYPE.DEFAULT: - case LoaderResource.XHR_RESPONSE_TYPE.TEXT: - /* falls through */ - default: - return 'text/plain'; - } - } -} - -// eslint-disable-next-line @typescript-eslint/no-namespace -namespace LoaderResource { - /** - * When the resource starts to load. - * - * @memberof PIXI.LoaderResource - * @callback OnStartSignal - * @param {Resource} resource - The resource that the event happened on. - */ - export type OnStartSignal = (resource: LoaderResource) => void; - /** - * When the resource reports loading progress. - * - * @memberof PIXI.LoaderResource - * @callback OnProgressSignal - * @param {Resource} resource - The resource that the event happened on. - * @param {number} percentage - The progress of the load in the range [0, 1]. - */ - export type OnProgressSignal = (resource: LoaderResource, percentage: number) => void; - /** - * When the resource finishes loading. - * - * @memberof PIXI.LoaderResource - * @callback OnCompleteSignal - * @param {Resource} resource - The resource that the event happened on. - */ - export type OnCompleteSignal = (resource: LoaderResource) => void; - - /** - * The types of resources a resource could represent. - * - * @static - * @readonly - * @enum {number} - * @memberof PIXI.LoaderResource - */ - export enum STATUS_FLAGS { - /** None */ - NONE= 0, - /** Data URL */ - DATA_URL= (1 << 0), - /** Complete */ - COMPLETE= (1 << 1), - /** Loading */ - LOADING= (1 << 2), - } - - /** - * The types of resources a resource could represent. - * - * @static - * @readonly - * @enum {number} - * @memberof PIXI.LoaderResource - */ - export enum TYPE { - /** Unknown */ - UNKNOWN= 0, - /** JSON */ - JSON= 1, - /** XML */ - XML= 2, - /** Image */ - IMAGE= 3, - /** Audio */ - AUDIO= 4, - /** Video */ - VIDEO= 5, - /** Plain text */ - TEXT= 6, - } - - /** - * The types of loading a resource can use. - * - * @static - * @readonly - * @enum {number} - * @memberof PIXI.LoaderResource - */ - export enum LOAD_TYPE { - /** Uses XMLHttpRequest to load the resource. */ - XHR = 1, - /** Uses an `Image` object to load the resource. */ - IMAGE = 2, - /** Uses an `Audio` object to load the resource. */ - AUDIO = 3, - /** Uses a `Video` object to load the resource. */ - VIDEO = 4, - } - - /** - * The XHR ready states, used internally. - * - * @static - * @readonly - * @enum {string} - * @memberof PIXI.LoaderResource - */ - export enum XHR_RESPONSE_TYPE { - /** string */ - DEFAULT = 'text', - /** ArrayBuffer */ - BUFFER = 'arraybuffer', - /** Blob */ - BLOB = 'blob', - /** Document */ - DOCUMENT = 'document', - /** Object */ - JSON = 'json', - /** String */ - TEXT = 'text', - } - - export const _loadTypeMap: Dict = { - // images - gif: LoaderResource.LOAD_TYPE.IMAGE, - png: LoaderResource.LOAD_TYPE.IMAGE, - bmp: LoaderResource.LOAD_TYPE.IMAGE, - jpg: LoaderResource.LOAD_TYPE.IMAGE, - jpeg: LoaderResource.LOAD_TYPE.IMAGE, - tif: LoaderResource.LOAD_TYPE.IMAGE, - tiff: LoaderResource.LOAD_TYPE.IMAGE, - webp: LoaderResource.LOAD_TYPE.IMAGE, - tga: LoaderResource.LOAD_TYPE.IMAGE, - svg: LoaderResource.LOAD_TYPE.IMAGE, - 'svg+xml': LoaderResource.LOAD_TYPE.IMAGE, // for SVG data urls - - // audio - mp3: LoaderResource.LOAD_TYPE.AUDIO, - ogg: LoaderResource.LOAD_TYPE.AUDIO, - wav: LoaderResource.LOAD_TYPE.AUDIO, - - // videos - mp4: LoaderResource.LOAD_TYPE.VIDEO, - webm: LoaderResource.LOAD_TYPE.VIDEO, - }; - - export const _xhrTypeMap: Dict = { - // xml - xhtml: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - html: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - htm: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - xml: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - tmx: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - svg: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - - // This was added to handle Tiled Tileset XML, but .tsx is also a TypeScript React Component. - // Since it is way less likely for people to be loading TypeScript files instead of Tiled files, - // this should probably be fine. - tsx: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - - // images - gif: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - png: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - bmp: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - jpg: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - jpeg: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - tif: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - tiff: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - webp: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - tga: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - - // json - json: LoaderResource.XHR_RESPONSE_TYPE.JSON, - - // text - text: LoaderResource.XHR_RESPONSE_TYPE.TEXT, - txt: LoaderResource.XHR_RESPONSE_TYPE.TEXT, - - // fonts - ttf: LoaderResource.XHR_RESPONSE_TYPE.BUFFER, - otf: LoaderResource.XHR_RESPONSE_TYPE.BUFFER, - }; - - // We can't set the `src` attribute to empty string, so on abort we set it to this 1px transparent gif - export const EMPTY_GIF = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='; -} - -export { LoaderResource }; - -/** @deprecated - Use LoaderResource instead */ -export type ILoaderResource = LoaderResource; diff --git a/packages/loaders/src/TextureLoader.ts b/packages/loaders/src/TextureLoader.ts deleted file mode 100644 index 4c4f9b09018..00000000000 --- a/packages/loaders/src/TextureLoader.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Texture } from '@pixi/core'; -import { LoaderResource } from './LoaderResource'; - -/** - * Loader plugin for handling Texture resources. - * - * @memberof PIXI - */ -export class TextureLoader -{ - /** - * Handle SVG elements a text, render with SVGResource. - */ - public static add(): void - { - LoaderResource.setExtensionLoadType('svg', LoaderResource.LOAD_TYPE.XHR); - LoaderResource.setExtensionXhrType('svg', LoaderResource.XHR_RESPONSE_TYPE.TEXT); - } - - /** - * Called after a resource is loaded. - * @see PIXI.Loader.loaderMiddleware - * @param resource - * @param {function} next - */ - public static use(resource: LoaderResource, next: (...args: any[]) => void): void - { - // create a new texture if the data is an Image object - if (resource.data && (resource.type === LoaderResource.TYPE.IMAGE || resource.extension === 'svg')) - { - const { data, url, name, metadata } = resource; - - Texture.fromLoader(data, url, name, metadata).then((texture) => - { - resource.texture = texture; - next(); - }) - // TODO: handle errors in Texture.fromLoader - // so we can pass them to the Loader - .catch(next); - } - else - { - next(); - } - } -} diff --git a/packages/loaders/src/base/AsyncQueue.ts b/packages/loaders/src/base/AsyncQueue.ts deleted file mode 100644 index 5a5c582abb9..00000000000 --- a/packages/loaders/src/base/AsyncQueue.ts +++ /dev/null @@ -1,299 +0,0 @@ -/** - * Smaller version of the async library constructs. - * @ignore - */ -function _noop(): void -{ /* empty */ -} - -/** - * Ensures a function is only called once. - * @ignore - * @param {function} fn - The function to wrap. - * @return {function} The wrapping function. - */ -function onlyOnce(fn: () => void): () => void -{ - return function onceWrapper(this: any, ...args: any) - { - if (fn === null) - { - throw new Error('Callback was already called.'); - } - - const callFn = fn; - - fn = null; - callFn.apply(this, args); - }; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface IQueue { - -} - -/** - * @private - * @memberof PIXI - */ -export class AsyncQueueItem -{ - data: TaskData; - callback: (...args: any[]) => void; - - /** - * @private - */ - constructor(data: TaskData, callback: (...args: any[]) => void) - { - this.data = data; - this.callback = callback; - } -} - -/** - * @private - * @memberof PIXI - */ -export class AsyncQueue -{ - workers = 0; - - concurrency: number; - buffer: number; - - saturated: () => void = _noop; - unsaturated: () => void = _noop; - empty: () => void = _noop; - drain: () => void = _noop; - error: (err: Error, task: TaskData) => void = _noop; - - started = false; - paused = false; - - private _worker: (x: TaskData, next: () => void) => void; - _tasks: Array> = []; - - /** - * @private - */ - constructor(worker: (x: TaskData, next: () => void) => void, concurrency = 1) - { - this._worker = worker; - - if (concurrency === 0) - { - throw new Error('Concurrency must not be zero'); - } - - this.concurrency = concurrency; - this.buffer = concurrency / 4.0; - } - - private _insert = (data: any, insertAtFront: boolean, callback?: () => void) => - { - if (callback && typeof callback !== 'function') - { - throw new Error('task callback must be a function'); - } - - this.started = true; - - // eslint-disable-next-line no-eq-null,eqeqeq - if (data == null && this.idle()) - { - // call drain immediately if there are no tasks - setTimeout(() => this.drain(), 1); - - return; - } - - const item = new AsyncQueueItem( - data, - typeof callback === 'function' ? callback : _noop - ); - - if (insertAtFront) - { - this._tasks.unshift(item); - } - else - { - this._tasks.push(item); - } - - setTimeout(this.process, 1); - }; - - process = (): void => - { - while (!this.paused && this.workers < this.concurrency && this._tasks.length) - { - const task = this._tasks.shift(); - - if (this._tasks.length === 0) - { - this.empty(); - } - - this.workers += 1; - - if (this.workers === this.concurrency) - { - this.saturated(); - } - - this._worker(task.data, onlyOnce(this._next(task))); - } - }; - - /** - * @private - */ - _next(task: AsyncQueueItem): (...args: any) => void - { - return (...args: any) => - { - this.workers -= 1; - - task.callback(...args); - - // eslint-disable-next-line no-eq-null,eqeqeq - if (args[0] != null) - { - this.error(args[0], task.data); - } - - if (this.workers <= (this.concurrency - this.buffer)) - { - this.unsaturated(); - } - - if (this.idle()) - { - this.drain(); - } - - this.process(); - }; - } - - // That was in object - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - push(data: any, callback?: (...args: any[]) => void): void - { - this._insert(data, false, callback); - } - - kill(): void - { - this.workers = 0; - this.drain = _noop; - this.started = false; - this._tasks = []; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - unshift(data: any, callback?: (...args: any[]) => void): void - { - this._insert(data, true, callback); - } - - length(): number - { - return this._tasks.length; - } - - running(): number - { - return this.workers; - } - - idle(): boolean - { - return this._tasks.length + this.workers === 0; - } - - pause(): void - { - if (this.paused === true) - { - return; - } - - this.paused = true; - } - - resume(): void - { - if (this.paused === false) - { - return; - } - - this.paused = false; - - // Need to call this.process once per concurrent - // worker to preserve full concurrency after pause - for (let w = 1; w <= this.concurrency; w++) - { - this.process(); - } - } - - /** - * Iterates an array in series. - * - * @param {Array.<*>} array - Array to iterate. - * @param {function} iterator - Function to call for each element. - * @param {function} callback - Function to call when done, or on error. - * @param {boolean} [deferNext=false] - Break synchronous each loop by calling next with a setTimeout of 1. - */ - static eachSeries(array: Array, iterator: (x: any, next: (err?: any) => void) => void, - callback?: (err?: any) => void, deferNext?: boolean): void - { - let i = 0; - const len = array.length; - - function next(err?: any) - { - if (err || i === len) - { - if (callback) - { - callback(err); - } - - return; - } - - if (deferNext) - { - setTimeout(() => - { - iterator(array[i++], next); - }, 1); - } - else - { - iterator(array[i++], next); - } - } - - next(); - } - - /** - * Async queue implementation, - * - * @param {function} worker - The worker function to call for each task. - * @param {number} concurrency - How many workers to run in parrallel. - * @return {*} The async queue object. - */ - static queue(worker: (x: any, next: (...args: any) => void) => void, concurrency?: number): AsyncQueue - { - return new AsyncQueue(worker, concurrency); - } -} diff --git a/packages/loaders/src/base/Signal.ts b/packages/loaders/src/base/Signal.ts deleted file mode 100644 index 4078ee58308..00000000000 --- a/packages/loaders/src/base/Signal.ts +++ /dev/null @@ -1,236 +0,0 @@ -/* jshint -W097 */ - -/** - * @memberof PIXI - */ -export class SignalBinding -{ - _fn: any; - _once: boolean; - _next: SignalBinding; - _prev: SignalBinding; - _owner: Signal; - _thisArg: any; - - /** - * SignalBinding constructor. - * @constructs SignalBinding - * @param {Function} fn - Event handler to be called. - * @param {Boolean} [once=false] - Should this listener be removed after dispatch - * @param {object} [thisArg] - The context of the callback function. - * @api private - */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - constructor(fn: CbType, once = false, thisArg: any) - { - this._fn = fn; - this._once = once; - this._thisArg = thisArg; - this._next = this._prev = this._owner = null; - } - - detach(): boolean - { - if (this._owner === null) return false; - this._owner.detach(this); - - return true; - } -} - -/** - * @private - */ -function _addSignalBinding(self: Signal, node: SignalBinding) -{ - if (!self._head) - { - self._head = node; - self._tail = node; - } - else - { - self._tail._next = node; - node._prev = self._tail; - self._tail = node; - } - - node._owner = self; - - return node; -} - -/** - * @memberof PIXI - */ -export class Signal void> -{ - _head: SignalBinding; - _tail: SignalBinding; - - /** - * MiniSignal constructor. - * @example - * let mySignal = new Signal(); - * let binding = mySignal.add(onSignal); - * mySignal.dispatch('foo', 'bar'); - * mySignal.detach(binding); - */ - constructor() - { - this._head = this._tail = undefined; - } - - /** - * Return an array of attached SignalBinding. - * - * @param {Boolean} [exists=false] - We only need to know if there are handlers. - * @returns {PIXI.SignalBinding[]|Boolean} Array of attached SignalBinding or Boolean if called with exists = true - * @api public - */ - handlers(exists = false): Array> | boolean - { - let node = this._head; - - if (exists) return !!node; - - const ee = []; - - while (node) - { - ee.push(node); - node = node._next; - } - - return ee; - } - - /** - * Return true if node is a SignalBinding attached to this MiniSignal - * - * @param {PIXI.SignalBinding} node - Node to check. - * @returns {Boolean} True if node is attache to mini-signal - */ - has(node: SignalBinding): boolean - { - if (!(node instanceof SignalBinding)) - { - throw new Error('MiniSignal#has(): First arg must be a SignalBinding object.'); - } - - return node._owner === this; - } - - /** - * Dispaches a signal to all registered listeners. - * - * @returns {Boolean} Indication if we've emitted an event. - */ - dispatch(...args: any[]): boolean - { - let node = this._head; - - if (!node) return false; - - while (node) - { - if (node._once) this.detach(node); - node._fn.apply(node._thisArg, args); - node = node._next; - } - - return true; - } - - /** - * Register a new listener. - * - * @param {Function} fn - Callback function. - * @param {object} [thisArg] - The context of the callback function. - * @returns {PIXI.SignalBinding} The SignalBinding node that was added. - */ - add(fn: CbType, thisArg: any = null): SignalBinding - { - if (typeof fn !== 'function') - { - throw new Error('MiniSignal#add(): First arg must be a Function.'); - } - - return _addSignalBinding(this, new SignalBinding(fn, false, thisArg)); - } - - /** - * Register a new listener that will be executed only once. - * - * @param {Function} fn - Callback function. - * @param {object} [thisArg] - The context of the callback function. - * @returns {PIXI.SignalBinding} The SignalBinding node that was added. - */ - once(fn: CbType, thisArg: any = null): SignalBinding - { - if (typeof fn !== 'function') - { - throw new Error('MiniSignal#once(): First arg must be a Function.'); - } - - return _addSignalBinding(this, new SignalBinding(fn, true, thisArg)); - } - - /** - * Remove binding object. - * - * @param {PIXI.SignalBinding} node - The binding node that will be removed. - * @returns {Signal} The instance on which this method was called. - * @api public */ - detach(node: SignalBinding): this - { - if (!(node instanceof SignalBinding)) - { - throw new Error('MiniSignal#detach(): First arg must be a SignalBinding object.'); - } - if (node._owner !== this) return this; // todo: or error? - - if (node._prev) node._prev._next = node._next; - if (node._next) node._next._prev = node._prev; - - if (node === this._head) - { // first node - this._head = node._next; - if (node._next === null) - { - this._tail = null; - } - } - else if (node === this._tail) - { // last node - this._tail = node._prev; - this._tail._next = null; - } - - node._owner = null; - - return this; - } - - /** - * Detach all listeners. - * - * @returns {Signal} The instance on which this method was called. - */ - detachAll(): this - { - let node = this._head; - - if (!node) return this; - - this._head = this._tail = null; - - while (node) - { - node._owner = null; - node = node._next; - } - - return this; - } -} diff --git a/packages/loaders/src/base/encodeBinary.ts b/packages/loaders/src/base/encodeBinary.ts deleted file mode 100644 index 82d43c7f19d..00000000000 --- a/packages/loaders/src/base/encodeBinary.ts +++ /dev/null @@ -1,77 +0,0 @@ -const _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; - -/** - * Encodes binary into base64. - * - * @function encodeBinary - * @param {string} input - The input data to encode. - * @returns {string} The encoded base64 string - */ -export function encodeBinary(input: string): string -{ - let output = ''; - let inx = 0; - - while (inx < input.length) - { - // Fill byte buffer array - const bytebuffer = [0, 0, 0]; - const encodedCharIndexes = [0, 0, 0, 0]; - - for (let jnx = 0; jnx < bytebuffer.length; ++jnx) - { - if (inx < input.length) - { - // throw away high-order byte, as documented at: - // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data - bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; - } - else - { - bytebuffer[jnx] = 0; - } - } - - // Get each encoded character, 6 bits at a time - // index 1: first 6 bits - encodedCharIndexes[0] = bytebuffer[0] >> 2; - - // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2) - encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); - - // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3) - encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); - - // index 3: forth 6 bits (6 least significant bits from input byte 3) - encodedCharIndexes[3] = bytebuffer[2] & 0x3f; - - // Determine whether padding happened, and adjust accordingly - const paddingBytes = inx - (input.length - 1); - - switch (paddingBytes) - { - case 2: - // Set last 2 characters to padding char - encodedCharIndexes[3] = 64; - encodedCharIndexes[2] = 64; - break; - - case 1: - // Set last character to padding char - encodedCharIndexes[3] = 64; - break; - - default: - break; // No padding - proceed - } - - // Now we will grab each appropriate character out of our keystring - // based on our index array and append it to the output string - for (let jnx = 0; jnx < encodedCharIndexes.length; ++jnx) - { - output += _keyStr.charAt(encodedCharIndexes[jnx]); - } - } - - return output; -} diff --git a/packages/loaders/src/base/parseUri.ts b/packages/loaders/src/base/parseUri.ts deleted file mode 100644 index 634c510f6fa..00000000000 --- a/packages/loaders/src/base/parseUri.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * function from npm package `parseUri`, converted to TS to avoid leftpad incident - * @param {string} str - * @param [opts] - options - * @param {boolean} [opts.strictMode] - type of parser - */ -export function parseUri(str: string, opts: { strictMode?: boolean }): any -{ - opts = opts || {}; - - const o = { - // eslint-disable-next-line max-len - key: ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'], - q: { - name: 'queryKey', - parser: /(?:^|&)([^&=]*)=?([^&]*)/g - }, - parser: { - // eslint-disable-next-line max-len - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, - // eslint-disable-next-line max-len - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ - } - }; - - const m = o.parser[opts.strictMode ? 'strict' : 'loose'].exec(str); - const uri: any = {}; - let i = 14; - - while (i--) uri[o.key[i]] = m[i] || ''; - - uri[o.q.name] = {}; - uri[o.key[12]].replace(o.q.parser, (_t0: any, t1: any, t2: any) => - { - if (t1) uri[o.q.name][t1] = t2; - }); - - return uri; -} diff --git a/packages/loaders/src/index.ts b/packages/loaders/src/index.ts deleted file mode 100644 index 28bd08f184d..00000000000 --- a/packages/loaders/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -export * from './AppLoaderPlugin'; -export * from './LoaderResource'; -export * from './Loader'; -export * from './TextureLoader'; - -import { parsing } from './middleware'; -import { Loader } from './Loader'; -import { TextureLoader } from './TextureLoader'; - -// parse any blob into more usable objects (e.g. Image) -Loader.registerPlugin({ use: parsing }); - -// parse any Image objects into textures -Loader.registerPlugin(TextureLoader); diff --git a/packages/loaders/src/middleware/caching.ts b/packages/loaders/src/middleware/caching.ts deleted file mode 100644 index 22046889d45..00000000000 --- a/packages/loaders/src/middleware/caching.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Dict } from '@pixi/utils'; -import { LoaderResource } from '../LoaderResource'; - -// a simple in-memory cache for resources -const cache: Dict = {}; - -/** - * A simple in-memory cache for resource. - * - * @ignore - * @function caching - * @example - * import { Loader, middleware } from 'resource-loader'; - * const loader = new Loader(); - * loader.use(middleware.caching); - * @param resource - Current Resource - * @param next - Callback when complete - */ -export function caching(resource: LoaderResource, next: (...args: any) => void): void -{ - // if cached, then set data and complete the resource - if (cache[resource.url]) - { - resource.data = cache[resource.url]; - resource.complete(); // marks resource load complete and stops processing before middlewares - } - // if not cached, wait for complete and store it in the cache. - else - { - resource.onComplete.once(function doCache(this: LoaderResource) { cache[this.url] = this.data; }); - } - - next(); -} diff --git a/packages/loaders/src/middleware/index.ts b/packages/loaders/src/middleware/index.ts deleted file mode 100644 index 50a88c2d7cc..00000000000 --- a/packages/loaders/src/middleware/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './caching'; -export * from './parsing'; diff --git a/packages/loaders/src/middleware/parsing.ts b/packages/loaders/src/middleware/parsing.ts deleted file mode 100644 index 896282751df..00000000000 --- a/packages/loaders/src/middleware/parsing.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { LoaderResource } from '../LoaderResource'; -import { encodeBinary } from '../base/encodeBinary'; - -const Url = self.URL || self.webkitURL; - -/** - * A middleware for transforming XHR loaded Blobs into more useful objects - * - * @ignore - * @function parsing - * @example - * import { Loader, middleware } from 'resource-loader'; - * const loader = new Loader(); - * loader.use(middleware.parsing); - * @param resource - Current Resource - * @param next - Callback when complete - */ -export function parsing(resource: LoaderResource, next: (...args: any) => void): void -{ - if (!resource.data) - { - next(); - - return; - } - - // if this was an XHR load of a blob - if (resource.xhr && resource.xhrType === LoaderResource.XHR_RESPONSE_TYPE.BLOB) - { - // if there is no blob support we probably got a binary string back - if (!self.Blob || typeof resource.data === 'string') - { - const type = resource.xhr.getResponseHeader('content-type'); - - // this is an image, convert the binary string into a data url - if (type && type.indexOf('image') === 0) - { - resource.data = new Image(); - resource.data.src = `data:${type};base64,${encodeBinary(resource.xhr.responseText)}`; - - resource.type = LoaderResource.TYPE.IMAGE; - - // wait until the image loads and then callback - resource.data.onload = () => - { - resource.data.onload = null; - - next(); - }; - - // next will be called on load - return; - } - } - // if content type says this is an image, then we should transform the blob into an Image object - else if (resource.data.type.indexOf('image') === 0) - { - const src = Url.createObjectURL(resource.data); - - resource.blob = resource.data; - resource.data = new Image(); - resource.data.src = src; - - resource.type = LoaderResource.TYPE.IMAGE; - - // cleanup the no longer used blob after the image loads - // TODO: Is this correct? Will the image be invalid after revoking? - resource.data.onload = () => - { - Url.revokeObjectURL(src); - resource.data.onload = null; - - next(); - }; - - // next will be called on load. - return; - } - } - - next(); -} diff --git a/packages/loaders/test/AppLoaderPlugin.tests.ts b/packages/loaders/test/AppLoaderPlugin.tests.ts deleted file mode 100644 index fb691a83bd6..00000000000 --- a/packages/loaders/test/AppLoaderPlugin.tests.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { AppLoaderPlugin, Loader } from '@pixi/loaders'; -import { expect } from 'chai'; - -describe('AppLoaderPlugin', function () -{ - it('should contain loader property', function () - { - const obj = {}; - - AppLoaderPlugin.init.call(obj); - - expect(obj.loader).to.be.not.undefined; - expect(obj.loader).to.be.instanceof(Loader); - - AppLoaderPlugin.destroy.call(obj); - - expect(obj.loader).to.be.null; - }); - - it('should use sharedLoader option', function () - { - const obj = {}; - - AppLoaderPlugin.init.call(obj, { sharedLoader: true }); - - expect(obj.loader).to.be.not.undefined; - expect(obj.loader).to.be.instanceof(Loader); - expect(obj.loader).to.equal(Loader.shared); - - AppLoaderPlugin.destroy.call(obj); - - expect(obj.loader).to.be.null; - }); -}); diff --git a/packages/loaders/test/AsyncQueue.tests.ts b/packages/loaders/test/AsyncQueue.tests.ts deleted file mode 100644 index eb14fdcfbe9..00000000000 --- a/packages/loaders/test/AsyncQueue.tests.ts +++ /dev/null @@ -1,957 +0,0 @@ -import { AsyncQueue as async } from '../src/base/AsyncQueue'; // testing internal package! -import { expect } from 'chai'; - -describe('async', () => -{ - describe('queue', () => - { - it('basics', (done: () => void) => - { - const callOrder: Array = []; - const delays = [40, 20, 60, 20]; - - // worker1: --1-4 - // worker2: -2---3 - // order of completion: 2,1,4,3 - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callOrder.push(`process ${task}`); - callback('error', 'arg'); - }, delays.shift()); - }, 2); - - q.push(1, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(1); - callOrder.push('callback 1'); - }); - q.push(2, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(2); - callOrder.push('callback 2'); - }); - q.push(3, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(0); - callOrder.push('callback 3'); - }); - q.push(4, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(0); - callOrder.push('callback 4'); - }); - expect(q.length()).to.equal(4); - expect(q.concurrency).to.equal(2); - - q.drain = () => - { - expect(callOrder).to.eql([ - 'process 2', 'callback 2', - 'process 1', 'callback 1', - 'process 4', 'callback 4', - 'process 3', 'callback 3', - ]); - expect(q.concurrency).to.equal(2); - expect(q.length()).to.equal(0); - done(); - }; - }); - - it('default concurrency', (done: () => void) => - { - const callOrder: Array = []; - const delays = [40, 20, 60, 20]; - - // order of completion: 1,2,3,4 - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callOrder.push(`process ${task}`); - callback('error', 'arg'); - }, delays.shift()); - }); - - q.push(1, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(3); - callOrder.push('callback 1'); - }); - q.push(2, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(2); - callOrder.push('callback 2'); - }); - q.push(3, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(1); - callOrder.push('callback 3'); - }); - q.push(4, (err, arg) => - { - expect(err).to.equal('error'); - expect(arg).to.equal('arg'); - expect(q.length()).to.equal(0); - callOrder.push('callback 4'); - }); - expect(q.length()).to.equal(4); - expect(q.concurrency).to.equal(1); - - q.drain = () => - { - expect(callOrder).to.eql([ - 'process 1', 'callback 1', - 'process 2', 'callback 2', - 'process 3', 'callback 3', - 'process 4', 'callback 4', - ]); - expect(q.concurrency).to.equal(1); - expect(q.length()).to.equal(0); - done(); - }; - }); - - it('zero concurrency', (done: () => void) => - { - expect(() => - { - async.queue((task: any, callback: (...args: any) => void): void => - { - callback(null, task); - }, 0); - }).to.throw(); - done(); - }); - - it('error propagation', (done: () => void) => - { - const results: Array = []; - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - callback(task.name === 'foo' ? new Error('fooError') : null); - }, 2); - - q.drain = () => - { - expect(results).to.eql(['bar', 'fooError']); - done(); - }; - - q.push({ name: 'bar' }, (err) => - { - if (err) - { - results.push('barError'); - - return; - } - - results.push('bar'); - }); - - q.push({ name: 'foo' }, (err) => - { - if (err) - { - results.push('fooError'); - - return; - } - - results.push('foo'); - }); - }); - - it('global error handler', (done: () => void) => - { - const results: Array = []; - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - callback(task.name === 'foo' ? new Error('fooError') : null); - }, 2); - - q.error = (error, task) => - { - expect(error).to.exist; - expect(error.message).to.equal('fooError'); - expect(task.name).to.equal('foo'); - results.push('fooError'); - }; - - q.drain = () => - { - expect(results).to.eql(['fooError', 'bar']); - done(); - }; - - q.push({ name: 'foo' }); - - q.push({ name: 'bar' }, (err) => - { - expect(err).to.not.exist; - results.push('bar'); - }); - }); - - // The original queue implementation allowed the concurrency to be changed only - // on the same event loop during which a task was added to the queue. This - // test attempts to be a more robust test. - // Start with a concurrency of 1. Wait until a leter event loop and change - // the concurrency to 2. Wait again for a later loop then verify the concurrency - // Repeat that one more time by chaning the concurrency to 5. - it('changing concurrency', (done: () => void) => - { - const q = async.queue((_task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callback(); - }, 10); - }, 1); - - for (let i = 0; i < 50; ++i) - { - q.push(''); - } - - q.drain = () => - { - done(); - }; - - setTimeout(() => - { - expect(q.concurrency).to.equal(1); - q.concurrency = 2; - setTimeout(() => - { - expect(q.running()).to.equal(2); - q.concurrency = 5; - setTimeout(() => - { - expect(q.running()).to.equal(5); - }, 40); - }, 40); - }, 40); - }); - - it('push without callback', (done: () => void) => - { - const callOrder: Array = []; - const delays = [40, 20, 60, 20]; - - // worker1: --1-4 - // worker2: -2---3 - // order of completion: 2,1,4,3 - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callOrder.push(`process ${task}`); - callback('error', 'arg'); - }, delays.shift()); - }, 2); - - q.push(1); - q.push(2); - q.push(3); - q.push(4); - - q.drain = () => - { - expect(callOrder).to.eql([ - 'process 2', - 'process 1', - 'process 4', - 'process 3', - ]); - done(); - }; - }); - - it('push with non-function', (done: () => void) => - { - const q = async.queue(() => { /* empty */ }, 1); - - expect(() => - { - q.push({}, 1); - }).to.throw(); - done(); - }); - - it('unshift', (done: () => void) => - { - const queueOrder: Array = []; - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - queueOrder.push(task); - callback(); - }, 1); - - q.unshift(4); - q.unshift(3); - q.unshift(2); - q.unshift(1); - - setTimeout(() => - { - expect(queueOrder).to.eql([1, 2, 3, 4]); - done(); - }, 100); - }); - - it('too many callbacks', (done: () => void) => - { - const q = async.queue((_task: any, callback: (...args: any) => void): void => - { - callback(); - expect(() => - { - callback(); - }).to.throw(); - done(); - }, 2); - - q.push(1); - }); - - it('idle', (done: () => void) => - { - const q = async.queue((_task: any, callback: (...args: any) => void): void => - { - // Queue is busy when workers are running - expect(q.idle()).to.equal(false); - callback(); - }, 1); - - // Queue is idle before anything added - expect(q.idle()).to.equal(true); - - q.unshift(4); - q.unshift(3); - q.unshift(2); - q.unshift(1); - - // Queue is busy when tasks added - expect(q.idle()).to.equal(false); - - q.drain = () => - { - // Queue is idle after drain - expect(q.idle()).to.equal(true); - done(); - }; - }); - - it.skip('pause', (done: () => void) => - { - const callOrder: Array = []; - const taskTimeout = 80; - const pauseTimeout = taskTimeout * 2.5; - const resumeTimeout = taskTimeout * 4.5; - const tasks = [1, 2, 3, 4, 5, 6]; - - const elapsed = (() => - { - const start = Date.now(); - - return () => Math.round((Date.now() - start) / taskTimeout) * taskTimeout; - })(); - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - callOrder.push(`process ${task}`); - callOrder.push(`timeout ${elapsed()}`); - callback(); - }); - - function pushTask() - { - const task = tasks.shift(); - - if (!task) - { - return; - } - - setTimeout(() => - { - q.push(task); - pushTask(); - }, taskTimeout); - } - pushTask(); - - setTimeout(() => - { - q.pause(); - expect(q.paused).to.equal(true); - }, pauseTimeout); - - setTimeout(() => - { - q.resume(); - expect(q.paused).to.equal(false); - }, resumeTimeout); - - setTimeout(() => - { - expect(callOrder).to.eql([ - 'process 1', `timeout ${taskTimeout}`, - 'process 2', `timeout ${(taskTimeout * 2)}`, - 'process 3', `timeout ${(taskTimeout * 5)}`, - 'process 4', `timeout ${(taskTimeout * 5)}`, - 'process 5', `timeout ${(taskTimeout * 5)}`, - 'process 6', `timeout ${(taskTimeout * 6)}`, - ]); - done(); - }, (taskTimeout * tasks.length) + pauseTimeout + resumeTimeout); - }); - - it('pause in worker with concurrency', (done: () => void) => - { - const callOrder: Array = []; - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - if (task.isLongRunning) - { - q.pause(); - setTimeout(() => - { - callOrder.push(task.id); - q.resume(); - callback(); - }, 50); - } - else - { - callOrder.push(task.id); - setTimeout(callback, 10); - } - }, 10); - - q.push({ id: 1, isLongRunning: true }); - q.push({ id: 2 }); - q.push({ id: 3 }); - q.push({ id: 4 }); - q.push({ id: 5 }); - - q.drain = () => - { - expect(callOrder).to.eql([1, 2, 3, 4, 5]); - done(); - }; - }); - - it('pause with concurrency', (done: () => void) => - { - const callOrder: Array = []; - const taskTimeout = 40; - const pauseTimeout = taskTimeout / 2; - const resumeTimeout = taskTimeout * 2.75; - const tasks = [1, 2, 3, 4, 5, 6]; - - const elapsed = (() => - { - const start = Date.now(); - - return () => Math.round((Date.now() - start) / taskTimeout) * taskTimeout; - })(); - - const q = async.queue((task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callOrder.push(`process ${task}`); - callOrder.push(`timeout ${elapsed()}`); - callback(); - }, taskTimeout); - }, 2); - - for (let i = 0; i < tasks.length; ++i) - { - q.push(tasks[i]); - } - - setTimeout(() => - { - q.pause(); - expect(q.paused).to.equal(true); - }, pauseTimeout); - - setTimeout(() => - { - q.resume(); - expect(q.paused).to.equal(false); - }, resumeTimeout); - - setTimeout(() => - { - expect(q.running()).to.equal(2); - }, resumeTimeout + 10); - - setTimeout(() => - { - expect(callOrder).to.eql([ - 'process 1', `timeout ${taskTimeout}`, - 'process 2', `timeout ${taskTimeout}`, - 'process 3', `timeout ${(taskTimeout * 4)}`, - 'process 4', `timeout ${(taskTimeout * 4)}`, - 'process 5', `timeout ${(taskTimeout * 5)}`, - 'process 6', `timeout ${(taskTimeout * 5)}`, - ]); - done(); - }, (taskTimeout * tasks.length) + pauseTimeout + resumeTimeout); - }); - - it('start paused', (done: () => void) => - { - const q = async.queue((_task: any, callback: (...args: any) => void): void => - { - setTimeout(() => - { - callback(); - }, 40); - }, 2); - - q.pause(); - - q.push(1); - q.push(2); - q.push(3); - - setTimeout(() => - { - q.resume(); - }, 5); - - setTimeout(() => - { - expect(q._tasks.length).to.equal(1); - expect(q.running()).to.equal(2); - q.resume(); - }, 15); - - q.drain = () => - { - done(); - }; - }); - - it('kill', (done: () => void) => - { - const q = async.queue((/* task, callback */) => - { - setTimeout(() => - { - throw new Error('Function should never be called'); - }, 20); - }, 1); - - q.drain = () => - { - throw new Error('Function should never be called'); - }; - - q.push(0); - - q.kill(); - - setTimeout(() => - { - expect(q.length()).to.equal(0); - done(); - }, 40); - }); - - it('events', (done: () => void) => - { - const calls: Array = []; - const q = async.queue((task, cb) => - { - // nop - calls.push(`process ${task}`); - setTimeout(cb, 10); - }, 3); - - q.concurrency = 3; - - q.saturated = () => - { - expect(q.running()).to.equal(3, 'queue should be saturated now'); - calls.push('saturated'); - }; - q.empty = () => - { - expect(q.length()).to.equal(0, 'queue should be empty now'); - calls.push('empty'); - }; - q.drain = () => - { - expect(q.length() === 0 && q.running() === 0) - .to.equal(true, 'queue should be empty now and no more workers should be running'); - calls.push('drain'); - expect(calls).to.eql([ - 'process foo', - 'process bar', - 'saturated', - 'process zoo', - 'foo cb', - 'saturated', - 'process poo', - 'bar cb', - 'empty', - 'saturated', - 'process moo', - 'zoo cb', - 'poo cb', - 'moo cb', - 'drain', - ]); - done(); - }; - q.push('foo', () => calls.push('foo cb')); - q.push('bar', () => calls.push('bar cb')); - q.push('zoo', () => calls.push('zoo cb')); - q.push('poo', () => calls.push('poo cb')); - q.push('moo', () => calls.push('moo cb')); - }); - - it('empty', (done: () => void) => - { - const calls: Array = []; - const q = async.queue((task, cb) => - { - // nop - calls.push(`process ${task}`); - setTimeout(cb, 1); - }, 3); - - q.drain = () => - { - expect(q.length() === 0 && q.running() === 0) - .to.equal(true, 'queue should be empty now and no more workers should be running'); - calls.push('drain'); - expect(calls).to.eql([ - 'drain', - ]); - done(); - }; - q.push(); - }); - - it('saturated', (done: () => void) => - { - let saturatedCalled = false; - const q = async.queue((task, cb) => - { - setTimeout(cb, 1); - }, 2); - - q.saturated = () => - { - saturatedCalled = true; - }; - q.drain = () => - { - expect(saturatedCalled).to.equal(true, 'saturated not called'); - done(); - }; - - q.push('foo'); - q.push('bar'); - q.push('baz'); - q.push('moo'); - }); - - it('started', (done: () => void) => - { - const q = async.queue((task, cb) => - { - cb(null, task); - }); - - expect(q.started).to.equal(false); - q.push(undefined); - expect(q.started).to.equal(true); - done(); - }); - - context('q.saturated(): ', () => - { - it('should call the saturated callback if tasks length is concurrency', (done: () => void) => - { - const calls: Array = []; - const q = async.queue((task, cb) => - { - calls.push(`process ${task}`); - setTimeout(cb, 1); - }, 4); - - q.saturated = () => - { - calls.push('saturated'); - }; - q.empty = () => - { - expect(calls.indexOf('saturated')).to.be.above(-1); - setTimeout(() => - { - expect(calls).eql([ - 'process foo0', - 'process foo1', - 'process foo2', - 'saturated', - 'process foo3', - 'foo0 cb', - 'saturated', - 'process foo4', - 'foo1 cb', - 'foo2 cb', - 'foo3 cb', - 'foo4 cb', - ]); - done(); - }, 50); - }; - q.push('foo0', () => calls.push('foo0 cb')); - q.push('foo1', () => calls.push('foo1 cb')); - q.push('foo2', () => calls.push('foo2 cb')); - q.push('foo3', () => calls.push('foo3 cb')); - q.push('foo4', () => calls.push('foo4 cb')); - }); - }); - - context('q.unsaturated(): ', () => - { - it('should have a default buffer property that equals 25% of the concurrenct rate', (done: () => void) => - { - const calls: Array = []; - const q = async.queue((task, cb) => - { - // nop - calls.push(`process ${task}`); - setTimeout(cb, 1); - }, 10); - - expect(q.buffer).to.equal(2.5); - done(); - }); - it('should allow a user to change the buffer property', (done: () => void) => - { - const calls: Array = []; - const q = async.queue((task, cb) => - { - // nop - calls.push(`process ${task}`); - setTimeout(cb, 1); - }, 10); - - q.buffer = 4; - expect(q.buffer).to.not.equal(2.5); - expect(q.buffer).to.equal(4); - done(); - }); - it('should call the unsaturated callback if tasks length is less than concurrency minus buffer', - (done: () => void) => - { // eslint-disable-line max-len - const calls: Array = []; - const q = async.queue((task: any, cb: () => void) => - { - calls.push(`process ${task}`); - setTimeout(cb, 1); - }, 4); - - q.unsaturated = () => - { - calls.push('unsaturated'); - }; - q.empty = () => - { - expect(calls.indexOf('unsaturated')).to.be.above(-1); - setTimeout(() => - { - expect(calls).eql([ - 'process foo0', - 'process foo1', - 'process foo2', - 'process foo3', - 'foo0 cb', - 'unsaturated', - 'process foo4', - 'foo1 cb', - 'unsaturated', - 'foo2 cb', - 'unsaturated', - 'foo3 cb', - 'unsaturated', - 'foo4 cb', - 'unsaturated', - ]); - done(); - }, 50); - }; - q.push('foo0', () => calls.push('foo0 cb')); - q.push('foo1', () => calls.push('foo1 cb')); - q.push('foo2', () => calls.push('foo2 cb')); - q.push('foo3', () => calls.push('foo3 cb')); - q.push('foo4', () => calls.push('foo4 cb')); - }); - }); - }); - - describe('eachSeries', () => - { - function eachIteratee(args: Array, x: number, callback: () => void) - { - setTimeout(() => - { - args.push(x); - callback(); - }, x * 25); - } - - function eachNoCallbackIteratee(done: () => void, x: number, callback: () => void) - { - expect(x).to.equal(1); - callback(); - done(); - } - - it('eachSeries', (done: () => void) => - { - const args: Array = []; - - async.eachSeries([1, 3, 2], eachIteratee.bind({ }, args), (err) => - { - expect(err).to.equal(undefined, `${err} passed instead of 'null'`); - expect(args).to.eql([1, 3, 2]); - done(); - }); - }); - - it('empty array', (done: () => void) => - { - async.eachSeries([], (x: number, callback: () => void) => - { - expect(false).to.equal(true, 'iteratee should not be called'); - callback(); - }, (err) => - { - if (err) - { - throw err; - } - - expect(true).to.equal(true, 'should call callback'); - }); - setTimeout(done, 25); - }); - - it('array modification', (done: () => void) => - { - const arr = [1, 2, 3, 4]; - - async.eachSeries(arr, (x, callback) => - { - setTimeout(callback, 1); - }, () => - { - expect(true).to.equal(true, 'should call callback'); - }); - - arr.pop(); - arr.splice(0, 1); - - setTimeout(done, 50); - }); - - // bug #782. Remove in next major release - it('single item', (done: () => void) => - { - let sync = true; - - async.eachSeries( - [1], - (i, cb) => - { - cb(null); - }, - () => - { - expect(sync).to.equal(true, 'callback not called on same tick'); - } - ); - sync = false; - done(); - }); - - // bug #782. Remove in next major release - it('single item', (done: () => void) => - { - let sync = true; - - async.eachSeries( - [1], - (i, cb) => - { - cb(null); - }, - () => - { - expect(sync).to.equal(true, 'callback not called on same tick'); - } - ); - sync = false; - done(); - }); - - it('error', (done: () => void) => - { - const callOrder: Array = []; - - async.eachSeries( - [1, 2, 3], - (x: any, callback: (x: string) => void) => - { - callOrder.push(x); - callback('error'); - }, - (err: string) => - { - expect(callOrder).to.eql([1]); - expect(err).to.equal('error'); - } - ); - setTimeout(done, 50); - }); - - it('no callback', (done: () => void) => - { - async.eachSeries([1], eachNoCallbackIteratee.bind(this, done)); - }); - }); -}); diff --git a/packages/loaders/test/Loader.tests.ts b/packages/loaders/test/Loader.tests.ts deleted file mode 100644 index ec09541c63a..00000000000 --- a/packages/loaders/test/Loader.tests.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { Loader } from '@pixi/loaders'; -import { Texture, ImageResource, SVGResource } from '@pixi/core'; -import { TextureCache } from '@pixi/utils'; -import { SCALE_MODES } from '@pixi/constants'; -import { createServer } from './resources'; - -import { expect } from 'chai'; - -const createRandomName = () => `image${(Math.random() * 10000) | 0}`; - -describe('Loader', function () -{ - before(function () - { - this.server = createServer(8125); - this.baseUrl = 'http://localhost:8125'; - }); - - after(function () - { - this.server.close(); - this.server = null; - this.baseUrl = null; - }); - - it('should exist', function () - { - expect(Loader).to.be.a('function'); - }); - - it('should have shared loader', function () - { - expect(Loader.shared).to.not.be.undefined; - expect(Loader.shared).to.be.instanceof(Loader); - }); - - it('should basic load an image using the TextureLoader', function (done) - { - const loader = new Loader(); - const name = createRandomName(); - const url = `${this.baseUrl}/bunny.png`; - - loader.add(name, url); - loader.load((ldr, resources) => - { - expect(ldr).equals(loader); - expect(name in resources).to.be.ok; - - const { texture } = resources[name]; - - expect(texture).instanceof(Texture); - expect(texture.baseTexture.valid).to.be.true; - expect(texture.baseTexture.resource).instanceof(ImageResource); - expect(texture.baseTexture.resource.url).equals(url); - expect(TextureCache[name]).equals(texture); - expect(TextureCache[url]).equals(texture); - loader.reset(); - texture.destroy(true); - expect(loader.resources[name]).to.be.undefined; - expect(TextureCache[name]).to.be.undefined; - expect(TextureCache[url]).to.be.undefined; - done(); - }); - }); - - it('should basic load an SVG using the TextureLoader', function (done) - { - const loader = new Loader(); - const name = createRandomName(); - const url = `${this.baseUrl}/logo.svg`; - - loader.add(name, url); - loader.load(() => - { - const { texture, data } = loader.resources[name]; - const { baseTexture } = texture; - - expect(typeof data).equals('string'); - expect(baseTexture.resource).instanceof(SVGResource); - expect(baseTexture.valid).to.be.true; - expect(baseTexture.width).equals(512); - expect(baseTexture.height).equals(512); - loader.reset(); - texture.destroy(true); - done(); - }); - }); - - it('should allow setting baseTexture properties through metadata', function (done) - { - const loader = new Loader(); - const name = createRandomName(); - const options = { - metadata: { - scaleMode: SCALE_MODES.NEAREST, - resolution: 2, - }, - }; - - loader.add(name, `${this.baseUrl}/bunny.png`, options).load(() => - { - const { texture } = loader.resources[name]; - const { scaleMode, resolution } = texture.baseTexture; - - expect(scaleMode).equals(SCALE_MODES.NEAREST); - expect(resolution).equals(2); - loader.reset(); - texture.destroy(true); - done(); - }); - }); - - it('should allow setting SVG width/height through metadata', function (done) - { - const loader = new Loader(); - const name = createRandomName(); - const options = { - metadata: { - resourceOptions: { - width: 128, - height: 256, - }, - }, - }; - - loader.add(name, `${this.baseUrl}/logo.svg`, options).load(() => - { - const { texture } = loader.resources[name]; - const { width, height } = texture.baseTexture; - - expect(width).equals(128); - expect(height).equals(256); - loader.reset(); - texture.destroy(true); - done(); - }); - }); - - it('should allow setting SVG scale through metadata', function (done) - { - const loader = new Loader(); - const name = createRandomName(); - const options = { - metadata: { - resourceOptions: { - scale: 0.5, - }, - }, - }; - - loader.add(name, `${this.baseUrl}/logo.svg`, options).load(() => - { - const { texture } = loader.resources[name]; - const { width, height } = texture.baseTexture; - - expect(width).equals(256); - expect(height).equals(256); - loader.reset(); - texture.destroy(true); - done(); - }); - }); -}); diff --git a/packages/loaders/test/LoaderBase.tests.ts b/packages/loaders/test/LoaderBase.tests.ts deleted file mode 100644 index 7b4be5db49b..00000000000 --- a/packages/loaders/test/LoaderBase.tests.ts +++ /dev/null @@ -1,951 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-expressions */ -import sinon from 'sinon'; -import { Loader, LoaderResource } from '@pixi/loaders'; -import { expect } from 'chai'; -import { fixtureData } from './fixtures/data'; -import { spritesheetMiddleware } from './fixtures/spritesheet'; -import { Dict } from '@pixi/utils/src'; -import { createServer } from './resources'; - -describe('Loader', () => -{ - before(function () - { - this.server = createServer(8126); - this.baseUrl = 'http://localhost:8126'; - }); - - after(function () - { - this.server.close(); - this.server = null; - this.baseUrl = null; - }); - - let loader: Loader = null; - - beforeEach(() => - { - loader = new Loader(fixtureData.baseUrl); - loader._beforeMiddleware = []; - loader._afterMiddleware = []; - }); - - it('should have correct properties', () => - { - expect(loader).to.have.property('baseUrl', fixtureData.baseUrl); - expect(loader).to.have.property('progress', 0); - }); - - it('should have correct public methods', () => - { - expect(loader).to.have.property('add').instanceOf(Function); - expect(loader).to.have.property('pre').instanceOf(Function); - expect(loader).to.have.property('use').instanceOf(Function); - expect(loader).to.have.property('reset').instanceOf(Function); - expect(loader).to.have.property('load').instanceOf(Function); - }); - - describe('#add', () => - { - const name = 'test-resource'; - const options = { - crossOrigin: true, - loadType: LoaderResource.LOAD_TYPE.IMAGE, - xhrType: LoaderResource.XHR_RESPONSE_TYPE.DOCUMENT, - }; - - function callback() { /* empty */ } - - it('creates a resource using all arguments', () => - { - loader.add(name, fixtureData.url, options, callback); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('crossOrigin', options.crossOrigin ? 'anonymous' : null); - expect(res).to.have.property('loadType', options.loadType); - expect(res).to.have.property('xhrType', options.xhrType); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just name, url, and options', () => - { - loader.add(name, fixtureData.url, options); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('crossOrigin', options.crossOrigin ? 'anonymous' : null); - expect(res).to.have.property('loadType', options.loadType); - expect(res).to.have.property('xhrType', options.xhrType); - }); - - it('creates a resource with just name, url, and a callback', () => - { - loader.add(name, fixtureData.url, callback); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just name and url', () => - { - loader.add(name, fixtureData.url); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - }); - - it('creates a resource with just url, options, and a callback', () => - { - loader.add(fixtureData.url, options, callback); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', fixtureData.url); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('crossOrigin', options.crossOrigin ? 'anonymous' : null); - expect(res).to.have.property('loadType', options.loadType); - expect(res).to.have.property('xhrType', options.xhrType); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just url and options', () => - { - loader.add(fixtureData.url, options); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', fixtureData.url); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('crossOrigin', options.crossOrigin ? 'anonymous' : null); - expect(res).to.have.property('loadType', options.loadType); - expect(res).to.have.property('xhrType', options.xhrType); - }); - - it('creates a resource with just url and a callback', () => - { - loader.add(fixtureData.url, callback); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', fixtureData.url); - expect(res).to.have.property('url', fixtureData.url); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just url', () => - { - loader.add(fixtureData.url); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', fixtureData.url); - expect(res).to.have.property('url', fixtureData.url); - }); - - it('creates a resource with just an object (name/url keys) and callback param', () => - { - loader.add({ name, url: fixtureData.url }, callback); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just an object (name/url/callback keys)', () => - { - loader.add({ name, url: fixtureData.url, onComplete: callback }); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', name); - expect(res).to.have.property('url', fixtureData.url); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('creates a resource with just an object (url/callback keys)', () => - { - loader.add({ url: fixtureData.url, onComplete: callback }); - - expect(loader._queue.length()).to.equal(1); - - const res = loader._queue._tasks[0].data; - - expect(res).to.be.an.instanceOf(LoaderResource); - expect(res).to.have.property('name', fixtureData.url); - expect(res).to.have.property('url', fixtureData.url); - - expect(res.onAfterMiddleware.handlers()) - .to.not.be.empty - .and.to.equal([callback]); - }); - - it('throws an error if url isn\'t passed', () => - { - expect(loader.add).to.throw(Error); - expect(() => loader.add(options)).to.throw(Error); - expect(() => loader.add(callback as any)).to.throw(Error); - expect(() => loader.add(options, callback)).to.throw(Error); - }); - - it('throws an error if we are already loading and you have no parent resource', () => - { - loader.add(fixtureData.url); - - loader.load(); - - expect(() => loader.add(fixtureData.dataUrlGif)).to.throw(Error); - }); - }); - - describe('#pre', () => - { - it('should add a middleware that runs before loading a resource', () => - { - loader.pre(() => { /* empty */ }); - - expect(loader._beforeMiddleware).to.have.length(1); - }); - }); - - describe('#use', () => - { - it('should add a middleware that runs after loading a resource', () => - { - loader.use(() => { /* empty */ }); - - expect(loader._afterMiddleware).to.have.length(1); - }); - }); - - describe('#reset', () => - { - it('should reset the loading state of the loader', () => - { - loader.loading = true; - expect(loader.loading).to.equal(true); - - loader.reset(); - expect(loader.loading).to.equal(false); - }); - - it('should reset the progress of the loader', () => - { - loader.progress = 100; - expect(loader.progress).to.equal(100); - - loader.reset(); - expect(loader.progress).to.equal(0); - }); - - it('should reset the queue/buffer of the loader', () => - { - loader._queue.push('me'); - expect(loader._queue.length()).to.equal(1); - expect(loader._queue.started).to.equal(true); - - loader.reset(); - expect(loader._queue.length()).to.equal(0); - expect(loader._queue.started).to.equal(false); - }); - - it('should reset the resources of the loader', () => - { - loader.add(fixtureData.url); - expect(loader.resources).to.not.be.empty; - - loader.reset(); - expect(loader.resources).to.be.empty; - }); - - it('with unloaded items continues to work', (done: () => void) => - { - const loader = new Loader(fixtureData.baseUrl, 2); - - loader.add(['hud.png', 'hud2.png', 'hud.json']).load(); - - setTimeout(() => - { - const spy = sinon.spy(); - - loader.reset(); - loader.add('hud2.json', spy).load(() => - { - expect(spy).to.have.been.calledOnce; - done(); - }); - }, 0); - }); - }); - - describe('#load', () => - { - it('should call start/complete when add was not called', (done: () => void) => - { - const spy = sinon.spy(); - const spy2 = sinon.spy(); - - loader.onStart.add(spy); - loader.onComplete.add(spy2); - - loader.load(() => - { - expect(spy).to.have.been.calledOnce; - expect(spy2).to.have.been.calledOnce; - done(); - }); - }); - - it('should call start/complete when given an empty set of resources', (done: () => void) => - { - const spy = sinon.spy(); - const spy2 = sinon.spy(); - - loader.onStart.add(spy); - loader.onComplete.add(spy2); - - loader.add([]).load(() => - { - expect(spy).to.have.been.calledOnce; - expect(spy2).to.have.been.calledOnce; - done(); - }); - }); - - it('should run the `before` middleware, before loading a resource', (done: () => void) => - { - const spy = sinon.spy((_res: any, next: any) => next()); - const spy2 = sinon.spy((_res: any, next: any) => next()); - - loader.pre(spy); - loader.pre(spy2); - - loader.add(fixtureData.dataUrlGif); - - loader.load(() => - { - expect(spy).to.have.been.calledOnce; - expect(spy2).to.have.been.calledOnce; - done(); - }); - }); - - it('should stop running the `before` middleware when one calls complete()', (done: () => void) => - { - const spy = sinon.spy((res: any, next: any) => - { - res.complete(); - next(); - }); - const spy2 = sinon.spy((_res: any, next: any) => next()); - - loader.pre(spy); - loader.pre(spy2); - - loader.add(fixtureData.dataUrlGif); - - loader.load(() => - { - expect(spy).to.have.been.calledOnce; - expect(spy2).to.have.not.been.called; - done(); - }); - }); - - it('should run the `after` middleware, after loading a resource', (done: () => void) => - { - const spy = sinon.spy((_res: any, next: any) => next()); - const spy2 = sinon.spy((_res: any, next: any) => next()); - - loader.use(spy); - loader.use(spy2); - - loader.add(fixtureData.dataUrlGif); - - loader.load(() => - { - expect(spy).to.have.been.calledOnce; - expect(spy2).to.have.been.calledOnce; - done(); - }); - }); - - it('should run `after` middleware for resources that have been completed in `before` middleware', - (done: () => void) => - { - const spy = sinon.spy((_res: any, next: any) => next()); - - loader - .pre((res, next) => - { - res.complete(); - next(); - }) - .use(spy) - .add(fixtureData.dataUrlGif) - .add(fixtureData.url) - .load(() => - { - expect(spy).to.have.been.calledTwice; - done(); - }); - }); - - it('should properly load the resource', (done: () => void) => - { - const spy = sinon.spy((loader: Loader, resources: Dict) => - { - expect(spy).to.have.been.calledOnce; - expect(loader.progress).to.equal(100); - expect(loader.loading).to.equal(false); - expect(loader.resources).to.equal(resources); - - expect(resources).to.not.be.empty; - expect(resources.res).to.be.ok; - expect(resources.res.isComplete).to.be.true; - - done(); - }); - - loader.add('res', fixtureData.dataUrlGif); - - loader.load(spy); - }); - }); - - describe('#_prepareUrl', () => - { - it('should return the url as-is for absolute urls', () => - { - const u1 = 'http://domain.com/image.png'; - const u2 = 'https://domain.com'; - const u3 = '//myshare/image.png'; - const u4 = '//myshare/image.png?v=1#me'; - - expect(loader._prepareUrl(u1)).to.equal(u1); - expect(loader._prepareUrl(u2)).to.equal(u2); - expect(loader._prepareUrl(u3)).to.equal(u3); - expect(loader._prepareUrl(u4)).to.equal(u4); - }); - - it('should add the baseUrl for relative urls (no trailing slash on baseUrl)', () => - { - const b = fixtureData.baseUrl; - const u1 = 'image.png'; - const u2 = '/image.png'; - const u3 = 'image.png?v=1'; - const u4 = '/image.png?v=1#me'; - - expect(loader._prepareUrl(u1)).to.equal(`${b}/${u1}`); - expect(loader._prepareUrl(u2)).to.equal(`${b}${u2}`); - expect(loader._prepareUrl(u3)).to.equal(`${b}/${u3}`); - expect(loader._prepareUrl(u4)).to.equal(`${b}${u4}`); - }); - - it('should add the baseUrl for relative urls (yes trailing slash on baseUrl)', () => - { - const b = loader.baseUrl = '/base/'; - const u1 = 'image.png'; - const u2 = '/image.png'; - const u3 = 'image.png?v=1'; - const u4 = '/image.png?v=1#me'; - - expect(loader._prepareUrl(u1)).to.equal(`${b}${u1}`); - expect(loader._prepareUrl(u2)).to.equal(`${b}${u2}`); - expect(loader._prepareUrl(u3)).to.equal(`${b}${u3}`); - expect(loader._prepareUrl(u4)).to.equal(`${b}${u4}`); - }); - - it('should add the queryString when set', () => - { - const b = fixtureData.baseUrl; - const u1 = 'image.png'; - const u2 = '/image.png'; - - loader.defaultQueryString = 'u=me&p=secret'; - - expect(loader._prepareUrl(u1)) - .to.equal(`${b}/${u1}?${loader.defaultQueryString}`); - - expect(loader._prepareUrl(u2)) - .to.equal(`${b}${u2}?${loader.defaultQueryString}`); - }); - - it('should add the defaultQueryString when set', () => - { - const b = fixtureData.baseUrl; - const u1 = 'image.png'; - const u2 = '/image.png'; - - loader.defaultQueryString = 'u=me&p=secret'; - - expect(loader._prepareUrl(u1)) - .to.equal(`${b}/${u1}?${loader.defaultQueryString}`); - - expect(loader._prepareUrl(u2)) - .to.equal(`${b}${u2}?${loader.defaultQueryString}`); - }); - - it('should add the defaultQueryString when if querystring already exists', () => - { - const b = fixtureData.baseUrl; - const u1 = 'image.png?v=1'; - - loader.defaultQueryString = 'u=me&p=secret'; - - expect(loader._prepareUrl(u1)) - .to.equal(`${b}/${u1}&${loader.defaultQueryString}`); - }); - - it('should add the defaultQueryString when hash exists', () => - { - const b = fixtureData.baseUrl; - - loader.defaultQueryString = 'u=me&p=secret'; - - expect(loader._prepareUrl('/image.png#me')) - .to.equal(`${b}/image.png?${loader.defaultQueryString}#me`); - }); - - it('should add the defaultQueryString when querystring and hash exists', () => - { - const b = fixtureData.baseUrl; - - loader.defaultQueryString = 'u=me&p=secret'; - - expect(loader._prepareUrl('/image.png?v=1#me')) - .to.equal(`${b}/image.png?v=1&${loader.defaultQueryString}#me`); - }); - }); - - describe('#_loadLoaderResource', () => - { - it('should run the before middleware before loading the resource', (done: () => void) => - { - const spy = sinon.spy(); - const res = {}; - - loader.pre(spy); - - loader._loadResource(res, null); - - setTimeout(() => - { - expect(spy).to.have.been.calledOnce - .and.calledOn(loader) - .and.calledWith(res); - - done(); - }, 16); - }); - - it('should load a resource passed into it', () => - { - const res = new LoaderResource('mock', fixtureData.url); - - res.load = sinon.spy(); - - loader._loadResource(res, null); - - expect(res.load).to.have.been.calledOnce; - }); - }); - - describe('#_onStart', () => - { - it('should emit the `start` event', (done: () => void) => - { - loader.onStart.add((_l) => - { - expect(_l).to.equal(loader); - - done(); - }); - - loader._onStart(); - }); - }); - - describe('#_onComplete', () => - { - it('should emit the `complete` event', (done: () => void) => - { - loader.onComplete.add((_l, resources) => - { - expect(_l).to.equal(loader); - expect(resources).to.equal(loader.resources); - - done(); - }); - - loader._onComplete(); - }); - }); - - describe('#_onLoad', () => - { - it('should emit the `progress` event', () => - { - const res = new LoaderResource('mock', fixtureData.url); - const spy = sinon.spy(); - - res._dequeue = sinon.spy(); - - loader.onProgress.once(spy); - - loader._onLoad(res); - - expect(spy).to.have.been.calledOnce; - }); - - it('should emit the `error` event when the resource has an error', () => - { - const res = new LoaderResource('mock', fixtureData.url); - const spy = sinon.spy(); - - res._dequeue = sinon.spy(); - - res.error = new Error('mock error'); - - loader.onError.once(spy); - - loader._onLoad(res); - - expect(spy).to.have.been.calledOnce; - }); - - it('should emit the `load` event when the resource loads successfully', () => - { - const res = new LoaderResource('mock', fixtureData.url); - const spy = sinon.spy(); - - res._dequeue = sinon.spy(); - - loader.onLoad.once(spy); - - loader._onLoad(res); - - expect(spy).to.have.been.calledOnce; - }); - - it('should run the after middleware', (done: () => void) => - { - const spy = sinon.spy(); - const res: any = {}; - - res._dequeue = sinon.spy(); - - loader.use(spy); - - loader._onLoad(res); - - setTimeout(() => - { - expect(spy).to.have.been.calledOnce - .and.calledOn(loader) - .and.calledWith(res); - - done(); - }, 16); - }); - }); - - describe('events', () => - { - describe('with no additional subresources', () => - { - it('should call progress for each loaded asset', (done: () => void) => - { - loader.add([ - { name: 'hud', url: 'hud.png' }, - { name: 'hud2', url: 'hud2.png' }, - ]); - - const spy = sinon.spy(); - - loader.onProgress.add(spy); - - loader.load(() => - { - expect(spy).to.have.been.calledTwice; - done(); - }); - }); - - it('should call progress for each loaded asset, even with low concurrency', (done: () => void) => - { - const loader = new Loader(fixtureData.baseUrl, 1); - - loader.add([ - { name: 'hud', url: 'hud.png' }, - { name: 'hud2', url: 'hud2.png' }, - ]); - - const spy = sinon.spy(); - - loader.onProgress.add(spy); - - loader.load(() => - { - expect(spy).to.have.been.calledTwice; - done(); - }); - }); - - it('should never have an invalid progress value', (done: () => void) => - { - const total = 7; - let i = 0; - - for (; i < total; i++) - { - loader.add([ - { name: `hud_${i}`, url: 'hud.png' }, - ]); - } - i = 0; - loader.onProgress.add((loader) => - { - i++; - expect(loader.progress).to.be.above(0); - if (i === total) - { - expect(loader.progress).to.be.at.most(100); - } - else - { - expect(loader.progress).to.be.below(100); - } - }); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - - it('progress should be 100% on complete', (done: () => void) => - { - loader.add([ - { name: 'hud', url: 'hud.png' }, - { name: 'hud2', url: 'hud2.png' }, - ]); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - }); - - describe('with one additional subresource', () => - { - it('should call progress for each loaded asset', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.png' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - const spy = sinon.spy(); - - loader.onProgress.add(spy); - - loader.load(() => - { - expect(spy).to.have.been.calledThrice; - done(); - }); - }); - - it('should call progress for each loaded asset, even with low concurrency', (done: () => void) => - { - const loader = new Loader(fixtureData.baseUrl, 1); - - loader.add([ - { name: 'hud2', url: 'hud2.png' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - const spy = sinon.spy(); - - loader.onProgress.add(spy); - - loader.load(() => - { - expect(spy).to.have.been.calledThrice; - done(); - }); - }); - - it('should never have an invalid progress value', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.png' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - const expectedProgressValues = [50, 75, 100]; - let i = 0; - - loader.onProgress.add((loader) => - { - expect(loader).to.have.property('progress', expectedProgressValues[i++]); - }); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - - it('progress should be 100% on complete', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.png' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - }); - - describe('with multiple additional subresources', () => - { - it('should call progress for each loaded asset', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.json' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - const spy = sinon.spy(); - - loader.onProgress.add(spy); - - loader.load(() => - { - expect(spy).to.have.callCount(4); - done(); - }); - }); - - it('should never have an invalid progress value', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.json' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - const expectedProgressValues = [25, 50, 75, 100]; - let i = 0; - - loader.onProgress.add((loader) => - { - expect(loader).to.have.property('progress', expectedProgressValues[i++]); - }); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - - it('progress should be 100% on complete', (done: () => void) => - { - loader.add([ - { name: 'hud2', url: 'hud2.json' }, - { name: 'hud_atlas', url: 'hud.json' }, - ]); - - loader.use(spritesheetMiddleware()); - - loader.load(() => - { - expect(loader).to.have.property('progress', 100); - done(); - }); - }); - }); - }); -}); diff --git a/packages/loaders/test/LoaderResource.test.ts b/packages/loaders/test/LoaderResource.test.ts deleted file mode 100644 index 5881402745e..00000000000 --- a/packages/loaders/test/LoaderResource.test.ts +++ /dev/null @@ -1,667 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-expressions */ -import sinon from 'sinon'; -import { LoaderResource } from '@pixi/loaders'; -import { expect } from 'chai'; -import { fixtureData } from './fixtures/data'; - -describe('LoaderResource', () => -{ - let request: any; - let res: LoaderResource; - let xhr: any; - let clock: any; - const name = 'test-resource'; - - before(() => - { - xhr = sinon.useFakeXMLHttpRequest(); - xhr.onCreate = (req: any) => - { - request = req; - }; - clock = sinon.useFakeTimers(); - }); - - after(() => - { - xhr.restore(); - clock.restore(); - }); - - beforeEach(() => - { - res = new LoaderResource(name, fixtureData.url); - request = null; - }); - - it('should construct properly with only a URL passed', () => - { - expect(res).to.have.property('name', name); - expect(res).to.have.property('type', LoaderResource.TYPE.UNKNOWN); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('data', null); - expect(res).to.have.property('crossOrigin', undefined); - expect(res).to.have.property('loadType', LoaderResource.LOAD_TYPE.XHR); - expect(res).to.have.property('xhrType', undefined); - expect(res).to.have.property('metadata').that.is.eql({}); - expect(res).to.have.property('error', null); - expect(res).to.have.property('xhr', null); - - expect(res).to.have.property('isDataUrl', false); - expect(res).to.have.property('isComplete', false); - expect(res).to.have.property('isLoading', false); - }); - - it('should construct properly with options passed', () => - { - const meta = { some: 'thing' }; - const res = new LoaderResource(name, fixtureData.url, { - crossOrigin: true, - loadType: LoaderResource.LOAD_TYPE.IMAGE, - xhrType: LoaderResource.XHR_RESPONSE_TYPE.BLOB, - metadata: meta, - }); - - expect(res).to.have.property('name', name); - expect(res).to.have.property('type', LoaderResource.TYPE.UNKNOWN); - expect(res).to.have.property('url', fixtureData.url); - expect(res).to.have.property('data', null); - expect(res).to.have.property('crossOrigin', 'anonymous'); - expect(res).to.have.property('loadType', LoaderResource.LOAD_TYPE.IMAGE); - expect(res).to.have.property('xhrType', LoaderResource.XHR_RESPONSE_TYPE.BLOB); - expect(res).to.have.property('metadata', meta); - expect(res).to.have.property('error', null); - expect(res).to.have.property('xhr', null); - - expect(res).to.have.property('isDataUrl', false); - expect(res).to.have.property('isComplete', false); - expect(res).to.have.property('isLoading', false); - }); - - describe('#complete', () => - { - it('should emit the `complete` event', () => - { - const spy = sinon.spy(); - - res.onComplete.add(spy); - - res.complete(); - - expect(spy).to.have.been.calledWith(res); - }); - - it('should remove events from the data element', () => - { - const data = { - addEventListener: () => { /* empty */ }, - removeEventListener: () => { /* empty */ }, - }; - const mock = sinon.mock(data); - - mock.expects('removeEventListener').once().withArgs('error'); - mock.expects('removeEventListener').once().withArgs('load'); - mock.expects('removeEventListener').once().withArgs('progress'); - mock.expects('removeEventListener').once().withArgs('canplaythrough'); - - res.data = data; - res.complete(); - - mock.verify(); - }); - - it('should remove events from the xhr element', () => - { - const data: any = { - addEventListener: () => { /* empty */ }, - removeEventListener: () => { /* empty */ }, - }; - const mock = sinon.mock(data); - - mock.expects('removeEventListener').once().withArgs('error'); - mock.expects('removeEventListener').once().withArgs('timeout'); - mock.expects('removeEventListener').once().withArgs('abort'); - mock.expects('removeEventListener').once().withArgs('progress'); - mock.expects('removeEventListener').once().withArgs('load'); - - res.xhr = data; - res.complete(); - - mock.verify(); - }); - }); - - describe('#abort', () => - { - it('should abort in-flight XHR requests', () => - { - res.load(); - - res.xhr.abort = sinon.spy(); - - res.abort(); - - expect(res.xhr.abort).to.have.been.calledOnce; - }); - - it('should abort in-flight XDR requests'); - - it('should abort in-flight Image requests', () => - { - res.data = new Image(); - res.data.src = fixtureData.url; - - expect(res.data.src).to.equal(fixtureData.url); - - res.abort(); - - expect(res.data.src).to.equal(LoaderResource.EMPTY_GIF); - }); - - it('should abort in-flight Video requests', () => - { - res.data = document.createElement('video'); - res.data.appendChild(document.createElement('source')); - - expect(res.data.firstChild).to.exist; - - res.abort(); - - expect(res.data.firstChild).to.not.exist; - }); - - it('should abort in-flight Audio requests', () => - { - res.data = document.createElement('audio'); - res.data.appendChild(document.createElement('source')); - - expect(res.data.firstChild).to.exist; - - res.abort(); - - expect(res.data.firstChild).to.not.exist; - }); - }); - - describe('#load', () => - { - it('should emit the start event', () => - { - const spy = sinon.spy(); - - res.onStart.add(spy); - - res.load(); - - expect(request).to.exist; - expect(spy).to.have.been.calledWith(res); - }); - - it('should emit the complete event', () => - { - const spy = sinon.spy(); - - res.onComplete.add(spy); - - res.load(); - - request.respond(200, fixtureData.dataJsonHeaders, fixtureData.dataJson); - - expect(request).to.exist; - expect(spy).to.have.been.calledWith(res); - }); - - it('should not load and emit a complete event if complete is called before load', () => - { - const spy = sinon.spy(); - - res.onComplete.add(spy); - - res.complete(); - res.load(); - - expect(request).not.to.exist; - expect(spy).to.have.been.calledWith(res); - }); - - it('should throw an error if complete is called twice', () => - { - function fn() - { - res.complete(); - } - - expect(fn).to.not.throw(Error); - expect(fn).to.throw(Error); - }); - - it('should load using a data url', (done) => - { - const res = new LoaderResource(name, fixtureData.dataUrlGif); - - res.onComplete.add(() => - { - expect(res).to.have.property('data').instanceOf(Image) - .and.is.an.instanceOf(HTMLImageElement) - .and.have.property('src', fixtureData.dataUrlGif); - - done(); - }); - - res.load(); - }); - - it('should load using a svg data url', (done) => - { - const res = new LoaderResource(name, fixtureData.dataUrlSvg); - - res.onComplete.add(() => - { - expect(res).to.have.property('data').instanceOf(Image) - .and.is.an.instanceOf(HTMLImageElement) - .and.have.property('src', fixtureData.dataUrlSvg); - - done(); - }); - - res.load(); - }); - - it('should load using XHR', (done) => - { - res.onComplete.add(() => - { - expect(res).to.have.property('data', fixtureData.dataJson); - done(); - }); - - res.load(); - - expect(request).to.exist; - - request.respond(200, fixtureData.dataJsonHeaders, fixtureData.dataJson); - }); - - it('should load using Image', () => - { - const res = new LoaderResource(name, fixtureData.url, { loadType: LoaderResource.LOAD_TYPE.IMAGE }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(Image) - .and.is.an.instanceOf(HTMLImageElement) - .and.have.property('src', fixtureData.url); - }); - - it('should load using Audio', () => - { - const res = new LoaderResource(name, fixtureData.url, { loadType: LoaderResource.LOAD_TYPE.AUDIO }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(HTMLAudioElement); - - expect(res.data.children).to.have.length(1); - expect(res.data.children[0]).to.have.property('src', fixtureData.url); - }); - - it('should load using Video', () => - { - const res = new LoaderResource(name, fixtureData.url, { loadType: LoaderResource.LOAD_TYPE.VIDEO }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(HTMLVideoElement); - - expect(res.data.children).to.have.length(1); - expect(res.data.children[0]).to.have.property('src', fixtureData.url); - }); - - it('should used the passed element for loading', () => - { - const img = new Image(); - const spy = sinon.spy(img, 'addEventListener'); - const res = new LoaderResource(name, fixtureData.url, { - loadType: LoaderResource.LOAD_TYPE.IMAGE, - metadata: { loadElement: img }, - }); - - res.load(); - - expect(spy).to.have.been.calledThrice; - expect(img).to.have.property('src', fixtureData.url); - - spy.restore(); - }); - - it('should used the passed element for loading, and skip assigning src', () => - { - const img = new Image(); - const spy = sinon.spy(img, 'addEventListener'); - const res = new LoaderResource(name, fixtureData.url, { - loadType: LoaderResource.LOAD_TYPE.IMAGE, - metadata: { loadElement: img, skipSource: true }, - }); - - res.load(); - - expect(spy).to.have.been.calledThrice; - expect(img).to.have.property('src', ''); - - spy.restore(); - }); - - it('should set withCredentials for XHR when crossOrigin specified', () => - { - const res = new LoaderResource(name, fixtureData.url, { - loadType: LoaderResource.LOAD_TYPE.XHR, - }); - - res.crossOrigin = 'use-credentials'; - - res.load(); - - expect(request.withCredentials).to.equal(true); - }); - }); - - describe('#load with timeout', () => - { - it('should abort XHR loads', (done) => - { - const res = new LoaderResource(name, fixtureData.url, { loadType: LoaderResource.LOAD_TYPE.XHR, timeout: 100 }); - - res.onComplete.add(() => - { - expect(res).to.have.property('error').instanceOf(Error); - expect(res).to.have.property('data').equal(null); - done(); - }); - - res.load(); - - expect(request).to.exist; - request.triggerTimeout(); - }); - - it('should abort Image loads', (done) => - { - const res = new LoaderResource(name, fixtureData.url, - { loadType: LoaderResource.LOAD_TYPE.IMAGE, timeout: 1000 }); - - res.onComplete.add(() => - { - expect(res).to.have.property('error').instanceOf(Error); - - expect(res).to.have.property('data').instanceOf(Image) - .and.is.an.instanceOf(HTMLImageElement) - .and.have.property('src', LoaderResource.EMPTY_GIF); - done(); - }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(Image) - .and.is.an.instanceOf(HTMLImageElement) - .and.have.property('src', fixtureData.url); - - clock.tick(1100); - }); - - it('should abort Audio loads', (done) => - { - const res = new LoaderResource(name, fixtureData.url, - { loadType: LoaderResource.LOAD_TYPE.AUDIO, timeout: 1000 }); - - res.onComplete.add(() => - { - expect(res).to.have.property('error').instanceOf(Error); - expect(res.data.children).to.have.length(0); - done(); - }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(HTMLAudioElement); - expect(res.data.children).to.have.length(1); - expect(res.data.children[0]).to.have.property('src', fixtureData.url); - - clock.tick(1100); - }); - - it('should abort Video loads', (done) => - { - const res = new LoaderResource(name, fixtureData.url, - { loadType: LoaderResource.LOAD_TYPE.VIDEO, timeout: 1000 }); - - res.onComplete.add(() => - { - expect(res).to.have.property('error').instanceOf(Error); - expect(res.data.children).to.have.length(0); - done(); - }); - - res.load(); - - expect(request).to.not.exist; - - expect(res).to.have.property('data').instanceOf(HTMLVideoElement); - expect(res.data.children).to.have.length(1); - expect(res.data.children[0]).to.have.property('src', fixtureData.url); - - clock.tick(1100); - }); - }); - - describe('#load inside cordova', () => - { - beforeEach(() => - { - xhr.status = 0; - }); - - it('should load resource even if the status is 0', () => - { - xhr.responseText = 'I am loaded resource'; - - res.xhr = xhr; - res._xhrOnLoad(); - - expect(res.isComplete).to.equal(true); - }); - - it('should load resource with array buffer data', () => - { - xhr.responseType = LoaderResource.XHR_RESPONSE_TYPE.BUFFER; - - res.xhr = xhr; - res._xhrOnLoad(); - - expect(res.isComplete).to.equal(true); - }); - }); - - describe('#_determineCrossOrigin', () => - { - it('should properly detect same-origin requests (#1)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com', - { hostname: 'google.com', port: '', protocol: 'https:' } - )).to.equal(''); - }); - - it('should properly detect same-origin requests (#2)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com:443', - { hostname: 'google.com', port: '', protocol: 'https:' } - )).to.equal(''); - }); - - it('should properly detect same-origin requests (#3)', () => - { - expect(res._determineCrossOrigin( - 'http://www.google.com:5678', - { hostname: 'www.google.com', port: '5678', protocol: 'http:' } - )).to.equal(''); - }); - - it('should properly detect cross-origin requests (#1)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com', - { hostname: 'google.com', port: '123', protocol: 'https:' } - )).to.equal('anonymous'); - }); - - it('should properly detect cross-origin requests (#2)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com', - { hostname: 'google.com', port: '', protocol: 'http:' } - )).to.equal('anonymous'); - }); - - it('should properly detect cross-origin requests (#3)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com', - { hostname: 'googles.com', port: '', protocol: 'https:' } - )).to.equal('anonymous'); - }); - - it('should properly detect cross-origin requests (#4)', () => - { - expect(res._determineCrossOrigin( - 'https://google.com', - { hostname: 'www.google.com', port: '123', protocol: 'https:' } - )).to.equal('anonymous'); - }); - it('should properly detect cross-origin requests (#5) - sandboxed iframe', () => - { - const originalOrigin = window.origin; - - // Set origin to 'null' to simulate sandboxed iframe without 'allow-same-origin' attribute - (window as any).origin = 'null'; - expect(res._determineCrossOrigin( - 'http://www.google.com:5678', - { hostname: 'www.google.com', port: '5678', protocol: 'http:' } - )).to.equal('anonymous'); - // Restore origin to prevent test leakage. - (window as any).origin = originalOrigin; - }); - }); - - describe('#_getExtension', () => - { - it('should return the proper extension', () => - { - res.url = 'http://www.google.com/image.png'; - expect(res._getExtension()).to.equal('png'); - - res.url = 'http://domain.net/really/deep/path/that/goes/for/a/while/movie.wmv'; - expect(res._getExtension()).to.equal('wmv'); - - res.url = 'http://somewhere.io/path.with.dots/and_a-bunch_of.symbols/data.txt'; - expect(res._getExtension()).to.equal('txt'); - - res.url = 'http://nowhere.me/image.jpg?query=true&string=false&name=real'; - expect(res._getExtension()).to.equal('jpg'); - - res.url = 'http://nowhere.me/image.jpeg?query=movie.wmv&file=data.json'; - expect(res._getExtension()).to.equal('jpeg'); - - res.url = 'http://nowhere.me/image.jpeg?query=movie.wmv&file=data.json'; - expect(res._getExtension()).to.equal('jpeg'); - - res.url = 'http://nowhere.me/image.jpeg?query=movie.wmv&file=data.json#/derp.mp3'; - expect(res._getExtension()).to.equal('jpeg'); - - res.url = 'http://nowhere.me/image.jpeg?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; - expect(res._getExtension()).to.equal('jpeg'); - - res.url = 'http://nowhere.me/image.jpeg#nothing-to-see-here?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; // eslint-disable-line max-len - expect(res._getExtension()).to.equal('jpeg'); - - res._setFlag(LoaderResource.STATUS_FLAGS.DATA_URL, true); - res.url = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY2BgYAAAAAQAAVzN/2kAAAAASUVORK5CYII='; // eslint-disable-line max-len - expect(res._getExtension()).to.equal('png'); - }); - }); - - describe('#_createSource', () => - { - it('Should return the correct src url', () => - { - res.url = 'http://www.google.com/audio.mp3'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://domain.net/really/deep/path/that/goes/for/a/while/movie.wmv'; - expect(res._createSource('video', res.url)).to.have.property('src', res.url); - - res.url = 'http://somewhere.io/path.with.dots/and_a-bunch_of.symbols/audio.mp3'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://nowhere.me/audio.mp3?query=true&string=false&name=real'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res.url = 'http://nowhere.me/audio.mp3#nothing-to-see-here?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; // eslint-disable-line max-len - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - - res._setFlag(LoaderResource.STATUS_FLAGS.DATA_URL, true); - res.url = 'data:audio/wave;base64,UklGRjIAAABXQVZFZm10IBIAAAABAAEAQB8AAEAfAAABAAgAAABmYWN0BAAAAAAAAABkYXRhAAAAAA=='; // eslint-disable-line max-len - expect(res._createSource('audio', res.url)).to.have.property('src', res.url); - }); - - it('Should correctly auto-detect the mime type', () => - { - res.url = 'http://www.google.com/audio.mp3'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://domain.net/really/deep/path/that/goes/for/a/while/movie.wmv'; - expect(res._createSource('video', res.url)).to.have.property('type', 'video/wmv'); - - res.url = 'http://somewhere.io/path.with.dots/and_a-bunch_of.symbols/audio.mp3'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://nowhere.me/audio.mp3?query=true&string=false&name=real'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://nowhere.me/audio.mp3?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res.url = 'http://nowhere.me/audio.mp3#nothing-to-see-here?query=movie.wmv&file=data.json#/derp.mp3&?me=two'; // eslint-disable-line max-len - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/mp3'); - - res._setFlag(LoaderResource.STATUS_FLAGS.DATA_URL, true); - res.url = 'data:audio/wave;base64,UklGRjIAAABXQVZFZm10IBIAAAABAAEAQB8AAEAfAAABAAgAAABmYWN0BAAAAAAAAABkYXRhAAAAAA=='; // eslint-disable-line max-len - expect(res._createSource('audio', res.url)).to.have.property('type', 'audio/wave'); - }); - }); -}); diff --git a/packages/loaders/test/TextureLoader.tests.ts b/packages/loaders/test/TextureLoader.tests.ts deleted file mode 100644 index 3a9dd53ff7b..00000000000 --- a/packages/loaders/test/TextureLoader.tests.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { TextureLoader, LoaderResource } from '@pixi/loaders'; -import { Texture } from '@pixi/core'; -import { BaseTextureCache, TextureCache } from '@pixi/utils'; -import sinon from 'sinon'; -import { expect } from 'chai'; - -describe('TextureLoader', function () -{ - it('should exist and return a function', function () - { - expect(TextureLoader).to.not.be.undefined; - expect(TextureLoader.use).to.be.a('function'); - }); - - it('should do nothing if the resource is not an image', function () - { - const spy = sinon.spy(); - const res = {}; - - TextureLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.texture).to.be.undefined; - }); - - it('should create a texture if resource is an image', function (done) - { - const name = `${(Math.random() * 10000) | 0}`; - const url = `http://localhost/doesnt_exist/${name}`; - const data = new Image(); - const type = LoaderResource.TYPE.IMAGE; - const res = { url, name, type, data, metadata: {} }; - - // Transparent image - data.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ' - + 'AAAADUlEQVQYV2P4GvD7PwAHvgNAdItKlAAAAABJRU5ErkJggg=='; - - TextureLoader.use(res, () => - { - expect(res.texture).to.be.an.instanceof(Texture); - - expect(BaseTextureCache).to.have.property(res.name, res.texture.baseTexture); - expect(BaseTextureCache).to.have.property(res.url, res.texture.baseTexture); - - expect(TextureCache).to.have.property(res.name, res.texture); - expect(TextureCache).to.have.property(res.url, res.texture); - - done(); - }); - }); -}); diff --git a/packages/loaders/test/fixtureData.ts b/packages/loaders/test/fixtureData.ts deleted file mode 100644 index 2503b65b8cb..00000000000 --- a/packages/loaders/test/fixtureData.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const fixtureData = { - url: 'http://localhost/file', - baseUrl: '/base/test/data', - dataUrlGif: 'data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==', - dataUrlSvg: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSczMCcgaGVpZ2h0PSczMCc+PGNpcmNsZSBjeD0nMTUnIGN5PScxNScgcj0nMTAnIC8+PC9zdmc+', // eslint-disable-line max-len - dataJson: '[{ "id": 12, "comment": "Hey there" }]', - dataJsonHeaders: { 'Content-Type': 'application/json' }, -}; diff --git a/packages/loaders/test/fixtures/data.ts b/packages/loaders/test/fixtures/data.ts deleted file mode 100644 index d0b8902f596..00000000000 --- a/packages/loaders/test/fixtures/data.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const fixtureData = { - url: 'http://localhost:8126/data/hud.png', - baseUrl: 'http://localhost:8126/data', - dataUrlGif: 'data:image/gif;base64,R0lGODlhAQABAPAAAP8REf///yH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==', - dataUrlSvg: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPSczMCcgaGVpZ2h0PSczMCc+PGNpcmNsZSBjeD0nMTUnIGN5PScxNScgcj0nMTAnIC8+PC9zdmc+', // eslint-disable-line max-len - dataJson: '[{ "id": 12, "comment": "Hey there" }]', - dataJsonHeaders: { 'Content-Type': 'application/json' }, -}; diff --git a/packages/loaders/test/fixtures/spritesheet.ts b/packages/loaders/test/fixtures/spritesheet.ts deleted file mode 100644 index 8dd52d425eb..00000000000 --- a/packages/loaders/test/fixtures/spritesheet.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Loader, LoaderResource } from '@pixi/loaders'; - -const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/; - -function posixSplitPath(filename: string) -{ - return splitPathRe.exec(filename).slice(1); -} - -function dirname(path: string) -{ - const result = posixSplitPath(path); - const root = result[0]; - let dir = result[1]; - - if (!root && !dir) - { - // No dirname whatsoever - return '.'; - } - - if (dir) - { - // It has a dirname, strip trailing slash - dir = dir.slice(0, -1); - } - - return root + dir; -} - -export function spritesheetMiddleware() -{ - return function spritesheetMiddleware(this: Loader, resource: LoaderResource, next: (...args: any) => void): void - { - // skip if no data, its not json, or it isn't spritesheet data - if (!resource.data || resource.type !== LoaderResource.TYPE.JSON || !resource.data.frames) - { - next(); - - return; - } - - const loadOptions = { - crossOrigin: resource.crossOrigin, - loadType: LoaderResource.LOAD_TYPE.IMAGE, - parentResource: resource, - }; - - const route = dirname(resource.url.replace(this.baseUrl, '')); - const name = `${resource.name}_image`; - const url = `${route}/${resource.data.meta.image}`; - - // load the image for this sheet - this.add(name, url, loadOptions, (/* res */) => next()); - }; -} diff --git a/packages/loaders/test/resources/data/hud.json b/packages/loaders/test/resources/data/hud.json deleted file mode 100644 index e2466e8a006..00000000000 --- a/packages/loaders/test/resources/data/hud.json +++ /dev/null @@ -1,92 +0,0 @@ -{"frames": { - -"0.png": -{ - "frame": {"x":14,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"1.png": -{ - "frame": {"x":14,"y":42,"w":12,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, - "sourceSize": {"w":12,"h":14} -}, -"2.png": -{ - "frame": {"x":14,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"3.png": -{ - "frame": {"x":42,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"4.png": -{ - "frame": {"x":28,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"5.png": -{ - "frame": {"x":14,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"6.png": -{ - "frame": {"x":0,"y":42,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"7.png": -{ - "frame": {"x":0,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"8.png": -{ - "frame": {"x":0,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"9.png": -{ - "frame": {"x":0,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}}, -"meta": { - "app": "http://www.texturepacker.com", - "version": "1.0", - "image": "hud.png", - "format": "RGBA8888", - "size": {"w":64,"h":64}, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" -} -} diff --git a/packages/loaders/test/resources/data/hud.png b/packages/loaders/test/resources/data/hud.png deleted file mode 100644 index bd8eb71b421c9011bfde19e1c2d3a864b5cb6c98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmV79PEL#3BQ_3L|HKoZl{G+@OzJ&At z#{J%Rzyq9uWwVQCh?bhv)_UW*5f8Y+10;8qRJ8Apvt3-(H&{Ii1(XWtt^EPd(0akv zT4hS+t+kH=vf1ilVqly!{;KPt0M)FWod$br^S^)sv}w?g>rd&>P{3VjP~QQ1BlGDq z-~m&4z*#jc?d8o1JfN{Ms8W{H(>GEa3Yf|RM$=$AZlefNETEHwdmK*q4D({qDwc%Xm@)1Zm@M(xKHCjbSEGGE(6WJhShEMQG> zmprRO0e7dt-c-o5!PQp*#cI%GvbHCP2dvr$SY3U!-Cz_@?g!Lrx%QU$s{jQwYPRdy z;3~C`0uoC%yeWzTX3GM1y(x+U000000Pe&$_yrGX-Jjf{00000NkvXXu0mjf4k+IY diff --git a/packages/loaders/test/resources/data/hud2.json b/packages/loaders/test/resources/data/hud2.json deleted file mode 100644 index 3eded7eb50e..00000000000 --- a/packages/loaders/test/resources/data/hud2.json +++ /dev/null @@ -1,92 +0,0 @@ -{"frames": { - -"0.png": -{ - "frame": {"x":14,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"1.png": -{ - "frame": {"x":14,"y":42,"w":12,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, - "sourceSize": {"w":12,"h":14} -}, -"2.png": -{ - "frame": {"x":14,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"3.png": -{ - "frame": {"x":42,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"4.png": -{ - "frame": {"x":28,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"5.png": -{ - "frame": {"x":14,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"6.png": -{ - "frame": {"x":0,"y":42,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"7.png": -{ - "frame": {"x":0,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"8.png": -{ - "frame": {"x":0,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}, -"9.png": -{ - "frame": {"x":0,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} -}}, -"meta": { - "app": "http://www.texturepacker.com", - "version": "1.0", - "image": "hud2.png", - "format": "RGBA8888", - "size": {"w":64,"h":64}, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" -} -} diff --git a/packages/loaders/test/resources/data/hud2.png b/packages/loaders/test/resources/data/hud2.png deleted file mode 100644 index bd8eb71b421c9011bfde19e1c2d3a864b5cb6c98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmV79PEL#3BQ_3L|HKoZl{G+@OzJ&At z#{J%Rzyq9uWwVQCh?bhv)_UW*5f8Y+10;8qRJ8Apvt3-(H&{Ii1(XWtt^EPd(0akv zT4hS+t+kH=vf1ilVqly!{;KPt0M)FWod$br^S^)sv}w?g>rd&>P{3VjP~QQ1BlGDq z-~m&4z*#jc?d8o1JfN{Ms8W{H(>GEa3Yf|RM$=$AZlefNETEHwdmK*q4D({qDwc%Xm@)1Zm@M(xKHCjbSEGGE(6WJhShEMQG> zmprRO0e7dt-c-o5!PQp*#cI%GvbHCP2dvr$SY3U!-Cz_@?g!Lrx%QU$s{jQwYPRdy z;3~C`0uoC%yeWzTX3GM1y(x+U000000Pe&$_yrGX-Jjf{00000NkvXXu0mjf4k+IY diff --git a/packages/loaders/test/resources/index.ts b/packages/loaders/test/resources/index.ts deleted file mode 100644 index f8cd47d39cd..00000000000 --- a/packages/loaders/test/resources/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import * as http from 'http'; -import * as fs from 'fs'; -import * as path from 'path'; - -const mimeTypes = { - '.js': 'text/javascript', - '.css': 'text/css', - '.json': 'application/json', - '.png': 'image/png', - '.jpg': 'image/jpg', - '.wav': 'audio/wav', -}; - -/** - * Very HTTP server to requesting files. - */ -const createServer = (port) => -{ - const server = http.createServer((request, response) => - { - const filePath = path.join(__dirname, request.url); - const extname = path.extname(filePath); - const contentType = mimeTypes[extname] || 'text/html'; - - fs.readFile(filePath, (error, content) => - { - if (error) - { - if (error.code === 'ENOENT') - { - response.writeHead(404); - response.end(`File not found: ${error.code} ..\n`); - response.end(); - } - else - { - response.writeHead(500); - response.end(`Internal server error: ${error.code} ..\n`); - response.end(); - } - } - else - { - response.writeHead(200, { 'Content-Type': contentType }); - response.end(content, 'utf-8'); - } - }); - }); - - server.listen(port); - - return server; -}; - -export { createServer }; diff --git a/packages/math-extras/global.d.ts b/packages/math-extras/global.d.ts index 8165d102301..3ecce994ae3 100644 --- a/packages/math-extras/global.d.ts +++ b/packages/math-extras/global.d.ts @@ -12,21 +12,20 @@ declare namespace GlobalMixins interface Rectangle { - intersects(other: Rectangle): boolean; + containsRect(other: import('@pixi/math').Rectangle): boolean; - containsRect(other: Rectangle): boolean; + equals(other: import('@pixi/math').Rectangle): boolean; - equals(other: Rectangle): boolean; + intersection(other: import('@pixi/math').Rectangle): import('@pixi/math').Rectangle; + intersection(other: import('@pixi/math').Rectangle, outRect: T): T; - intersection(other: Rectangle): Rectangle; - intersection(other: Rectangle, outRect: T): T; - - union(other: Rectangle): Rectangle; - union(other: Rectangle, outRect: T): T; + union(other: import('@pixi/math').Rectangle): import('@pixi/math').Rectangle; + union(other: import('@pixi/math').Rectangle, outRect: T): T; } } -interface Vector2Math { +interface Vector2Math +{ add(other: import('@pixi/math').IPointData): import('@pixi/math').Point; add(other: import('@pixi/math').IPointData, outPoint: T): T; diff --git a/packages/math-extras/package.json b/packages/math-extras/package.json index 583f8c4a45b..2aeb5fb5603 100644 --- a/packages/math-extras/package.json +++ b/packages/math-extras/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/math-extras", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/math-extras.js", - "module": "dist/esm/math-extras.js", - "bundle": "dist/browser/math-extras.js", - "bundleNoExports": true, + "module": "dist/esm/math-extras.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/math-extras.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/math-extras.js" + } + } + }, "description": "Useful methods for some math structures", "author": "Milton Candelero", "contributors": [ @@ -22,11 +33,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/math": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/math-extras/src/index.ts b/packages/math-extras/src/index.ts index 8f086ee214c..560da84449f 100644 --- a/packages/math-extras/src/index.ts +++ b/packages/math-extras/src/index.ts @@ -1,14 +1,14 @@ import './pointExtras'; import './rectangleExtras'; -import { IPointData, Point } from '@pixi/math'; +import type { IPointData } from '@pixi/core'; +import { Point } from '@pixi/core'; /** * The idea of a relative epsilon comparison is to find the difference between the two numbers, * and see if it is less than `Math.EPSILON`. * * _Note: Only available with **@pixi/math-extras**._ - * * @param {number} a - First floating number to compare. * @param {number} b - Second floating number to compare. * @returns {boolean} Returns `true` if the difference between the values is less than `Math.EPSILON`; otherwise `false`. @@ -20,7 +20,6 @@ export function floatEqual(a: number, b: number): boolean; * A good epsilon would be the N% of the largest of the two values or `Math.EPSILON`. * * _Note: Only available with **@pixi/math-extras**._ - * * @memberof PIXI * @param {number} a - First floating number to compare. * @param {number} b - Second floating number to compare. @@ -113,7 +112,6 @@ function genericLineIntersection( * The intersection point may land outside the extents of the lines. * * _Note: Only available with **@pixi/math-extras**._ - * * @param aStart - First point of the first line. * @param aEnd - Second point of the first line. * @param bStart - First point of the second line. @@ -127,7 +125,6 @@ export function lineIntersection(aStart: IPointData, aEnd: IPointData, bStart: I * The intersection point may land outside the extents of the lines. * * _Note: Only available with **@pixi/math-extras**._ - * * @memberof PIXI * @param aStart - First point of the first line. * @param aEnd - Second point of the first line. @@ -151,7 +148,6 @@ export function lineIntersection * The intersection point must land inside the extents of the segments or return a `NaN` Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @param aStart - Starting point of the first segment. * @param aEnd - Ending point of the first segment. * @param bStart - Starting point of the second segment. @@ -165,7 +161,6 @@ export function segmentIntersection(aStart: IPointData, aEnd: IPointData, bStart * The intersection point must land inside the extents of the segments or return a `NaN` Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @memberof PIXI * @param aStart - Starting point of the first segment. * @param aEnd - Ending point of the first segment. diff --git a/packages/math-extras/src/pointExtras.ts b/packages/math-extras/src/pointExtras.ts index 1797b10c6b8..511f1304a0d 100644 --- a/packages/math-extras/src/pointExtras.ts +++ b/packages/math-extras/src/pointExtras.ts @@ -1,11 +1,11 @@ -import { Point, IPointData, ObservablePoint } from '@pixi/math'; +import type { IPointData } from '@pixi/core'; +import { Point, ObservablePoint } from '@pixi/core'; const mixins: any = { /** * Adds `other` to `this` point and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method add * @memberof PIXI.Point# * @param {IPointData} other - The point to add to `this`. @@ -17,7 +17,6 @@ const mixins: any = { * Adds `other` to `this` point and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method add * @memberof PIXI.ObservablePoint# * @param {IPointData} other - The point to add to `this`. @@ -41,7 +40,6 @@ const mixins: any = { * Subtracts `other` from `this` point and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method subtract * @memberof PIXI.Point# * @param {IPointData} other - The point to subtract to `this`. @@ -53,7 +51,6 @@ const mixins: any = { * Subtracts `other` from `this` point and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method subtract * @memberof PIXI.ObservablePoint# * @param {IPointData} other - The point to subtract to `this`. @@ -77,7 +74,6 @@ const mixins: any = { * Multiplies component-wise `other` and `this` points and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method multiply * @memberof PIXI.Point# * @param {IPointData} other - The point to multiply with `this`. @@ -89,7 +85,6 @@ const mixins: any = { * Multiplies component-wise `other` and `this` points and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method multiply * @memberof PIXI.ObservablePoint# * @param {IPointData} other - The point to multiply with `this`. @@ -113,7 +108,6 @@ const mixins: any = { * Multiplies each component of `this` point with the number `scalar` and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method multiplyScalar * @memberof PIXI.Point# * @param {number} scalar - The number to multiply both components of `this`. @@ -125,7 +119,6 @@ const mixins: any = { * Multiplies each component of `this` point with the number `scalar` and outputs into `outPoint` or a new Point. * * _Note: Only available with **@pixi/math-extras**._ - * * @method multiplyScalar * @memberof PIXI.ObservablePoint# * @param {number} scalar - The number to multiply both components of `this`. @@ -150,7 +143,6 @@ const mixins: any = { * The dot product is the sum of the products of the corresponding components of two vectors. * * _Note: Only available with **@pixi/math-extras**._ - * * @method dot * @memberof PIXI.Point# * @param {IPointData} other - The other point to calculate the dot product with `this`. @@ -161,7 +153,6 @@ const mixins: any = { * The dot product is the sum of the products of the corresponding components of two vectors. * * _Note: Only available with **@pixi/math-extras**._ - * * @method dot * @memberof PIXI.ObservablePoint# * @param {IPointData} other - The other point to calculate the dot product with `this`. @@ -182,7 +173,6 @@ const mixins: any = { * This function returns the z component of the cross product of the two points. * * _Note: Only available with **@pixi/math-extras**._ - * * @method cross * @memberof PIXI.Point# * @param {IPointData} other - The other point to calculate the cross product with `this`. @@ -198,7 +188,6 @@ const mixins: any = { * This function returns the z component of the cross product of the two points. * * _Note: Only available with **@pixi/math-extras**._ - * * @method cross * @memberof PIXI.ObservablePoint# * @param {IPointData} other - The other point to calculate the cross product with `this`. @@ -224,7 +213,6 @@ const mixins: any = { * A normalized vector is a vector of magnitude (length) 1 * * _Note: Only available with **@pixi/math-extras**._ - * * @method normalize * @memberof PIXI.Point# * @param {IPointData} [outPoint] - A Point-like object in which to store the value, @@ -237,7 +225,6 @@ const mixins: any = { * A normalized vector is a vector of magnitude (length) 1 * * _Note: Only available with **@pixi/math-extras**._ - * * @method normalize * @memberof PIXI.ObservablePoint# * @param {IPointData} [outPoint] - A Point-like object in which to store the value, @@ -264,7 +251,6 @@ const mixins: any = { * Defined as the square root of the sum of the squares of each component. * * _Note: Only available with **@pixi/math-extras**._ - * * @method magnitude * @memberof PIXI.Point# * @returns {number} The magnitude (length) of the vector. @@ -275,7 +261,6 @@ const mixins: any = { * Defined as the square root of the sum of the squares of each component. * * _Note: Only available with **@pixi/math-extras**._ - * * @method magnitude * @memberof PIXI.ObservablePoint# * @returns {number} The magnitude (length) of the vector. @@ -293,7 +278,6 @@ const mixins: any = { * Defined as the sum of the squares of each component. * * _Note: Only available with **@pixi/math-extras**._ - * * @method magnitudeSquared * @memberof PIXI.Point# * @returns {number} The magnitude squared (length squared) of the vector. @@ -306,7 +290,6 @@ const mixins: any = { * Defined as the sum of the squares of each component. * * _Note: Only available with **@pixi/math-extras**._ - * * @method magnitudeSquared * @memberof PIXI.ObservablePoint# * @returns {number} The magnitude squared (length squared) of the vector. @@ -324,7 +307,6 @@ const mixins: any = { * `this.project(onto)` is the shadow cast by `this` on the line defined by `onto` . * * _Note: Only available with **@pixi/math-extras**._ - * * @method project * @memberof PIXI.Point# * @param {IPointData} onto - A non zero vector describing a line on which to project `this`. @@ -340,7 +322,6 @@ const mixins: any = { * `this.project(onto)` is the shadow cast by `this` on the line defined by `onto` . * * _Note: Only available with **@pixi/math-extras**._ - * * @method project * @memberof PIXI.ObservablePoint# * @param {IPointData} onto - A non zero vector describing a line on which to project `this`. @@ -372,7 +353,6 @@ const mixins: any = { * `this.reflect(normal)` is the reflection of `this` on that mirror. * * _Note: Only available with **@pixi/math-extras**._ - * * @method reflect * @memberof PIXI.Point# * @param {IPointData} normal - The normal vector of your reflecting plane. @@ -389,7 +369,6 @@ const mixins: any = { * `this.reflect(normal)` is the reflection of `this` on that mirror. * * _Note: Only available with **@pixi/math-extras**._ - * * @method reflect * @memberof PIXI.ObservablePoint# * @param {IPointData} normal - The normal vector of your reflecting plane. diff --git a/packages/math-extras/src/rectangleExtras.ts b/packages/math-extras/src/rectangleExtras.ts index 365abc72d07..3afd6eaaefa 100644 --- a/packages/math-extras/src/rectangleExtras.ts +++ b/packages/math-extras/src/rectangleExtras.ts @@ -1,4 +1,4 @@ -import { Rectangle } from '@pixi/math'; +import { Rectangle } from '@pixi/core'; /** * Determines whether the `other` Rectangle is contained within `this` Rectangle object. @@ -7,7 +7,6 @@ import { Rectangle } from '@pixi/math'; * not even other arealess rectangles. * * _Note: Only available with **@pixi/math-extras**._ - * * @method containsRect * @memberof PIXI.Rectangle# * @param {Rectangle} other - The Rectangle to fit inside `this`. @@ -27,7 +26,6 @@ Rectangle.prototype.containsRect = function containsRect(other: Rectangle): bool * Accepts `other` Rectangle and returns true if the given Rectangle is equal to `this` Rectangle. * * _Note: Only available with **@pixi/math-extras**._ - * * @method equals * @memberof PIXI.Rectangle# * @param {Rectangle} other - The Rectangle to compare with `this` @@ -51,8 +49,7 @@ Rectangle.prototype.equals = function equals(other: Rectangle): boolean * and will always return an empty rectangle with its properties set to zero. * * _Note: Only available with **@pixi/math-extras**._ - * - * @method intersects + * @method intersection * @memberof PIXI.Rectangle# * @param {Rectangle} other - The Rectangle to intersect with `this`. * @param {Rectangle} [outRect] - A Rectangle object in which to store the value, @@ -99,8 +96,7 @@ Rectangle.prototype.intersection = function intersection(ot * the horizontal and vertical space between the two rectangles. * * _Note: Only available with **@pixi/math-extras**._ - * - * @method intersects + * @method union * @memberof PIXI.Rectangle# * @param {Rectangle} other - The Rectangle to unite with `this`. * @param {Rectangle} [outRect] - A Rectangle object in which to store the value, diff --git a/packages/math-extras/test/Point.tests.ts b/packages/math-extras/test/Point.tests.ts index 1ea093e4004..955416190e2 100644 --- a/packages/math-extras/test/Point.tests.ts +++ b/packages/math-extras/test/Point.tests.ts @@ -1,329 +1,329 @@ -import { ObservablePoint, Point } from '@pixi/math'; -import { expect } from 'chai'; +import { ObservablePoint, Point } from '@pixi/core'; + import '@pixi/math-extras'; -describe('Point', function () +describe('Point', () => { - describe('add', function () + describe('add', () => { - it('should add component-wise', function () + it('should add component-wise', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.add(b); - expect(c.x).to.equal(4); - expect(c.y).to.equal(6); + expect(c.x).toEqual(4); + expect(c.y).toEqual(6); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.add(ob); - expect(oc.x).to.equal(4); - expect(oc.y).to.equal(6); + expect(oc.x).toEqual(4); + expect(oc.y).toEqual(6); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.add(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.add(ob, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.add(b, { x: 0, y: 0 }); - expect(c.x).to.equal(4); - expect(c.y).to.equal(6); + expect(c.x).toEqual(4); + expect(c.y).toEqual(6); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.add(ob, { x: 0, y: 0 }); - expect(oc.x).to.equal(4); - expect(oc.y).to.equal(6); + expect(oc.x).toEqual(4); + expect(oc.y).toEqual(6); }); - it('can take any IPointData as other input', function () + it('can take any IPointData as other input', () => { // Point const a = new Point(1, 2); const c = a.add({ x: 3, y: 4 }); - expect(c.x).to.equal(4); - expect(c.y).to.equal(6); + expect(c.x).toEqual(4); + expect(c.y).toEqual(6); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.add({ x: 3, y: 4 }); - expect(oc.x).to.equal(4); - expect(oc.y).to.equal(6); + expect(oc.x).toEqual(4); + expect(oc.y).toEqual(6); }); }); - describe('subtract', function () + describe('subtract', () => { - it('should subtract component-wise', function () + it('should subtract component-wise', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.subtract(b); - expect(c.x).to.equal(-2); - expect(c.y).to.equal(-2); + expect(c.x).toEqual(-2); + expect(c.y).toEqual(-2); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.subtract(ob); - expect(oc.x).to.equal(-2); - expect(oc.y).to.equal(-2); + expect(oc.x).toEqual(-2); + expect(oc.y).toEqual(-2); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.subtract(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.subtract(ob, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.subtract(b, { x: 0, y: 0 }); - expect(c.x).to.equal(-2); - expect(c.y).to.equal(-2); + expect(c.x).toEqual(-2); + expect(c.y).toEqual(-2); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.subtract(ob, { x: 0, y: 0 }); - expect(oc.x).to.equal(-2); - expect(oc.y).to.equal(-2); + expect(oc.x).toEqual(-2); + expect(oc.y).toEqual(-2); }); - it('can take any IPointData as other input', function () + it('can take any IPointData as other input', () => { // Point const a = new Point(1, 2); const c = a.subtract({ x: 3, y: 4 }); - expect(c.x).to.equal(-2); - expect(c.y).to.equal(-2); + expect(c.x).toEqual(-2); + expect(c.y).toEqual(-2); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.subtract({ x: 3, y: 4 }); - expect(oc.x).to.equal(-2); - expect(oc.y).to.equal(-2); + expect(oc.x).toEqual(-2); + expect(oc.y).toEqual(-2); }); }); - describe('multiply', function () + describe('multiply', () => { - it('should multiply component-wise', function () + it('should multiply component-wise', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.multiply(b); - expect(c.x).to.equal(3); - expect(c.y).to.equal(8); + expect(c.x).toEqual(3); + expect(c.y).toEqual(8); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.multiply(ob); - expect(oc.x).to.equal(3); - expect(oc.y).to.equal(8); + expect(oc.x).toEqual(3); + expect(oc.y).toEqual(8); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.multiply(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.multiply(ob, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.multiply(b, { x: 0, y: 0 }); - expect(c.x).to.equal(3); - expect(c.y).to.equal(8); + expect(c.x).toEqual(3); + expect(c.y).toEqual(8); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.multiply(ob, { x: 0, y: 0 }); - expect(oc.x).to.equal(3); - expect(oc.y).to.equal(8); + expect(oc.x).toEqual(3); + expect(oc.y).toEqual(8); }); - it('can take any IPointData as other input', function () + it('can take any IPointData as other input', () => { // Point const a = new Point(1, 2); const c = a.multiply({ x: 3, y: 4 }); - expect(c.x).to.equal(3); - expect(c.y).to.equal(8); + expect(c.x).toEqual(3); + expect(c.y).toEqual(8); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.multiply({ x: 3, y: 4 }); - expect(oc.x).to.equal(3); - expect(oc.y).to.equal(8); + expect(oc.x).toEqual(3); + expect(oc.y).toEqual(8); }); }); - describe('multiplyScalar', function () + describe('multiplyScalar', () => { - it('should multiply both components by a scalar', function () + it('should multiply both components by a scalar', () => { // Point const a = new Point(1, 2); const c = a.multiplyScalar(3); - expect(c.x).to.equal(3); - expect(c.y).to.equal(6); + expect(c.x).toEqual(3); + expect(c.y).toEqual(6); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.multiplyScalar(3); - expect(oc.x).to.equal(3); - expect(oc.y).to.equal(6); + expect(oc.x).toEqual(3); + expect(oc.y).toEqual(6); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const c = a.multiplyScalar(3, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.multiplyScalar(3, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const c = a.multiplyScalar(3, { x: 0, y: 0 }); - expect(c.x).to.equal(3); - expect(c.y).to.equal(6); + expect(c.x).toEqual(3); + expect(c.y).toEqual(6); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.multiplyScalar(3, { x: 0, y: 0 }); - expect(oc.x).to.equal(3); - expect(oc.y).to.equal(6); + expect(oc.x).toEqual(3); + expect(oc.y).toEqual(6); }); }); - describe('dot', function () + describe('dot', () => { - it('should multiply component-wise and then add both components', function () + it('should multiply component-wise and then add both components', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.dot(b); - expect(c).to.equal(11); + expect(c).toEqual(11); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.dot(ob); - expect(oc).to.equal(11); + expect(oc).toEqual(11); }); }); - describe('cross', function () + describe('cross', () => { - it('should return the magnitude of the result of a cross product', function () + it('should return the magnitude of the result of a cross product', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.cross(b); - expect(c).to.equal(-2); + expect(c).toEqual(-2); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.cross(ob); - expect(oc).to.equal(-2); + expect(oc).toEqual(-2); }); }); - describe('normalize', function () + describe('normalize', () => { - it('magnitude should be 1', function () + it('magnitude should be 1', () => { // Point const a = new Point(3, 4); @@ -331,7 +331,7 @@ describe('Point', function () const magnitude = Math.sqrt((c.x * c.x) + (c.y * c.y)); - expect(magnitude).to.be.closeTo(1, 0.001); + expect(magnitude).toBeCloseTo(1, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); @@ -339,25 +339,25 @@ describe('Point', function () const omagnitude = Math.sqrt((oc.x * oc.x) + (oc.y * oc.y)); - expect(omagnitude).to.be.closeTo(1, 0.001); + expect(omagnitude).toBeCloseTo(1, 0.001); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(3, 4); const c = a.normalize(a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.normalize(oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); @@ -365,7 +365,7 @@ describe('Point', function () const magnitude = Math.sqrt((c.x * c.x) + (c.y * c.y)); - expect(magnitude).to.be.closeTo(1, 0.001); + expect(magnitude).toBeCloseTo(1, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); @@ -373,192 +373,192 @@ describe('Point', function () const omagnitude = Math.sqrt((oc.x * oc.x) + (oc.y * oc.y)); - expect(omagnitude).to.be.closeTo(1, 0.001); + expect(omagnitude).toBeCloseTo(1, 0.001); }); }); - describe('magnitude', function () + describe('magnitude', () => { - it('should return the square root of the sum of the squares of each component', function () + it('should return the square root of the sum of the squares of each component', () => { const expectedMagnitude = Math.sqrt((3 * 3) + (4 * 4)); // Point const a = new Point(3, 4); const c = a.magnitude(); - expect(c).to.be.closeTo(expectedMagnitude, 0.001); + expect(c).toBeCloseTo(expectedMagnitude, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.magnitude(); - expect(oc).to.be.closeTo(expectedMagnitude, 0.001); + expect(oc).toBeCloseTo(expectedMagnitude, 0.001); }); - it('should return the sum of the squares of each component', function () + it('should return the sum of the squares of each component', () => { const expectedMagnitudeSquared = (3 * 3) + (4 * 4); // Point const a = new Point(3, 4); const c = a.magnitudeSquared(); - expect(c).to.be.closeTo(expectedMagnitudeSquared, 0.001); + expect(c).toBeCloseTo(expectedMagnitudeSquared, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.magnitudeSquared(); - expect(oc).to.equal(expectedMagnitudeSquared); + expect(oc).toEqual(expectedMagnitudeSquared); }); }); - describe('project', function () + describe('project', () => { - it('should return the vector projection of a vector onto another nonzero vector', function () + it('should return the vector projection of a vector onto another nonzero vector', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.project(b); - expect(c.x).to.be.closeTo(33 / 25, 0.001); - expect(c.y).to.be.closeTo(44 / 25, 0.001); + expect(c.x).toBeCloseTo(33 / 25, 0.001); + expect(c.y).toBeCloseTo(44 / 25, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.project(ob); - expect(oc.x).to.be.closeTo(33 / 25, 0.001); - expect(oc.y).to.be.closeTo(44 / 25, 0.001); + expect(oc.x).toBeCloseTo(33 / 25, 0.001); + expect(oc.y).toBeCloseTo(44 / 25, 0.001); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.project(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.project(ob, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.project(b, { x: 0, y: 0 }); - expect(c.x).to.be.closeTo(33 / 25, 0.001); - expect(c.y).to.be.closeTo(44 / 25, 0.001); + expect(c.x).toBeCloseTo(33 / 25, 0.001); + expect(c.y).toBeCloseTo(44 / 25, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.project(ob, { x: 0, y: 0 }); - expect(oc.x).to.be.closeTo(33 / 25, 0.001); - expect(oc.y).to.be.closeTo(44 / 25, 0.001); + expect(oc.x).toBeCloseTo(33 / 25, 0.001); + expect(oc.y).toBeCloseTo(44 / 25, 0.001); }); - it('can take any IPointData as other input', function () + it('can take any IPointData as other input', () => { // Point const a = new Point(1, 2); const c = a.project({ x: 3, y: 4 }); - expect(c.x).to.be.closeTo(33 / 25, 0.001); - expect(c.y).to.be.closeTo(44 / 25, 0.001); + expect(c.x).toBeCloseTo(33 / 25, 0.001); + expect(c.y).toBeCloseTo(44 / 25, 0.001); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.project({ x: 3, y: 4 }); - expect(oc.x).to.be.closeTo(33 / 25, 0.001); - expect(oc.y).to.be.closeTo(44 / 25, 0.001); + expect(oc.x).toBeCloseTo(33 / 25, 0.001); + expect(oc.y).toBeCloseTo(44 / 25, 0.001); }); }); - describe('reflect', function () + describe('reflect', () => { - it('should return the specular reflect vector', function () + it('should return the specular reflect vector', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.reflect(b); - expect(c.x).to.equal(-65); - expect(c.y).to.equal(-86); + expect(c.x).toEqual(-65); + expect(c.y).toEqual(-86); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.reflect(ob); - expect(oc.x).to.equal(-65); - expect(oc.y).to.equal(-86); + expect(oc.x).toEqual(-65); + expect(oc.y).toEqual(-86); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.reflect(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.reflect(ob, oa); - expect(oc).to.equal(oa); + expect(oc).toEqual(oa); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { // Point const a = new Point(1, 2); const b = new Point(3, 4); const c = a.reflect(b, { x: 0, y: 0 }); - expect(c.x).to.equal(-65); - expect(c.y).to.equal(-86); + expect(c.x).toEqual(-65); + expect(c.y).toEqual(-86); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const ob = new ObservablePoint(() => { /* empty */ }, {}, 3, 4); const oc = oa.reflect(ob, { x: 0, y: 0 }); - expect(oc.x).to.equal(-65); - expect(oc.y).to.equal(-86); + expect(oc.x).toEqual(-65); + expect(oc.y).toEqual(-86); }); - it('can take any IPointData as other input', function () + it('can take any IPointData as other input', () => { // Point const a = new Point(1, 2); const c = a.reflect({ x: 3, y: 4 }); - expect(c.x).to.equal(-65); - expect(c.y).to.equal(-86); + expect(c.x).toEqual(-65); + expect(c.y).toEqual(-86); // ObservablePoint const oa = new ObservablePoint(() => { /* empty */ }, {}, 1, 2); const oc = oa.reflect({ x: 3, y: 4 }); - expect(oc.x).to.equal(-65); - expect(oc.y).to.equal(-86); + expect(oc.x).toEqual(-65); + expect(oc.y).toEqual(-86); }); }); }); diff --git a/packages/math-extras/test/Rectangle.tests.ts b/packages/math-extras/test/Rectangle.tests.ts index 76de6039c6e..49423d211c8 100644 --- a/packages/math-extras/test/Rectangle.tests.ts +++ b/packages/math-extras/test/Rectangle.tests.ts @@ -1,12 +1,12 @@ -import { Rectangle } from '@pixi/math'; -import { expect } from 'chai'; +import { Rectangle } from '@pixi/core'; + import '@pixi/math-extras'; -describe('Rectangle', function () +describe('Rectangle', () => { - describe('containsRect', function () + describe('containsRect', () => { - it('should return true if all four corners are inside or on the edge of the rectangle', function () + it('should return true if all four corners are inside or on the edge of the rectangle', () => { /* +-----------------+-----------------+ @@ -25,52 +25,52 @@ describe('Rectangle', function () const d = new Rectangle(150, 50, 0, 0); // a contains c - expect(a.containsRect(c)).to.equal(true); + expect(a.containsRect(c)).toEqual(true); // but c doesn't contain a - expect(c.containsRect(a)).to.equal(false); + expect(c.containsRect(a)).toEqual(false); // b doesn't contain c - expect(a.containsRect(b)).to.equal(false); + expect(a.containsRect(b)).toEqual(false); // B contains D. An empty rectangle **CAN** be contained - expect(b.containsRect(d)).to.equal(true); + expect(b.containsRect(d)).toEqual(true); // Any rectangle with area contains itself - expect(a.containsRect(a.clone())).to.equal(true); - expect(b.containsRect(b.clone())).to.equal(true); - expect(c.containsRect(c.clone())).to.equal(true); + expect(a.containsRect(a.clone())).toEqual(true); + expect(b.containsRect(b.clone())).toEqual(true); + expect(c.containsRect(c.clone())).toEqual(true); // An empty rectangle can't contain anything, thus it can't contain itself - expect(d.containsRect(d.clone())).to.equal(false); + expect(d.containsRect(d.clone())).toEqual(false); }); }); - describe('equals', function () + describe('equals', () => { - it('should return true x, y, width and height match', function () + it('should return true x, y, width and height match', () => { const a = new Rectangle(0, 0, 100, 100); const b = new Rectangle(0, 0, 100, 100); const c = new Rectangle(50, 50, 100, 100); // a is equal to b - expect(a.equals(b)).to.equal(true); + expect(a.equals(b)).toEqual(true); // thus b is equal to a - expect(b.equals(a)).to.equal(true); + expect(b.equals(a)).toEqual(true); // c is not equal to a - expect(a.equals(c)).to.equal(false); + expect(a.equals(c)).toEqual(false); // any point is equal to themselves - expect(a.equals(a.clone())).to.equal(true); - expect(b.equals(b.clone())).to.equal(true); - expect(c.equals(c.clone())).to.equal(true); + expect(a.equals(a.clone())).toEqual(true); + expect(b.equals(b.clone())).toEqual(true); + expect(c.equals(c.clone())).toEqual(true); }); }); - describe('intersection', function () + describe('intersection', () => { it('should return a rectangle with the intersection if the area is > 0, otherwise an empty rectangle', - function () + () => { /* +--------+ @@ -93,69 +93,69 @@ describe('Rectangle', function () const intersectingEmpty = b.intersection(empty); const emptyIntersectsItself = empty.intersection(empty); - expect(d.x).to.equal(50); - expect(d.y).to.equal(50); - expect(d.width).to.equal(50); - expect(d.height).to.equal(50); + expect(d.x).toEqual(50); + expect(d.y).toEqual(50); + expect(d.width).toEqual(50); + expect(d.height).toEqual(50); - expect(e.x).to.equal(0); - expect(e.y).to.equal(0); - expect(e.width).to.equal(0); - expect(e.height).to.equal(0); + expect(e.x).toEqual(0); + expect(e.y).toEqual(0); + expect(e.width).toEqual(0); + expect(e.height).toEqual(0); // empty rectangles can't intersect or be intersected - expect(emptyIntersects.x).to.equal(0); - expect(emptyIntersects.y).to.equal(0); - expect(emptyIntersects.width).to.equal(0); - expect(emptyIntersects.height).to.equal(0); - - expect(intersectingEmpty.x).to.equal(0); - expect(intersectingEmpty.y).to.equal(0); - expect(intersectingEmpty.width).to.equal(0); - expect(intersectingEmpty.height).to.equal(0); - - expect(emptyIntersectsItself.x).to.equal(0); - expect(emptyIntersectsItself.y).to.equal(0); - expect(emptyIntersectsItself.width).to.equal(0); - expect(emptyIntersectsItself.height).to.equal(0); + expect(emptyIntersects.x).toEqual(0); + expect(emptyIntersects.y).toEqual(0); + expect(emptyIntersects.width).toEqual(0); + expect(emptyIntersects.height).toEqual(0); + + expect(intersectingEmpty.x).toEqual(0); + expect(intersectingEmpty.y).toEqual(0); + expect(intersectingEmpty.width).toEqual(0); + expect(intersectingEmpty.height).toEqual(0); + + expect(emptyIntersectsItself.x).toEqual(0); + expect(emptyIntersectsItself.y).toEqual(0); + expect(emptyIntersectsItself.width).toEqual(0); + expect(emptyIntersectsItself.height).toEqual(0); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { const a = new Rectangle(0, 0, 100, 100); const b = new Rectangle(50, 50, 100, 100); const c = a.intersection(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); }); }); - describe('union', function () + describe('union', () => { it('should return a rectangle that includes both rectangles (similar to enlarge)', - function () + () => { const a = new Rectangle(0, 0, 100, 100); const b = new Rectangle(50, 50, 100, 100); const c = a.union(b); - expect(c.x).to.equal(0); - expect(c.y).to.equal(0); - expect(c.width).to.equal(150); - expect(c.height).to.equal(150); + expect(c.x).toEqual(0); + expect(c.y).toEqual(0); + expect(c.width).toEqual(150); + expect(c.height).toEqual(150); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { const a = new Rectangle(0, 0, 100, 100); const b = new Rectangle(50, 50, 100, 100); const c = a.union(b, a); - expect(c).to.equal(a); + expect(c).toEqual(a); }); it('should return the same values as enalrge()', - function () + () => { const enlarged = new Rectangle(0, 0, 100, 100); const a = new Rectangle(0, 0, 100, 100); @@ -164,10 +164,10 @@ describe('Rectangle', function () enlarged.enlarge(b); - expect(c.x).to.equal(enlarged.x); - expect(c.y).to.equal(enlarged.y); - expect(c.width).to.equal(enlarged.width); - expect(c.height).to.equal(enlarged.height); + expect(c.x).toEqual(enlarged.x); + expect(c.y).toEqual(enlarged.y); + expect(c.width).toEqual(enlarged.width); + expect(c.height).toEqual(enlarged.height); }); }); }); diff --git a/packages/math-extras/test/floatEqual.tests.ts b/packages/math-extras/test/floatEqual.tests.ts index 89c1d92f430..e7f156bbab9 100644 --- a/packages/math-extras/test/floatEqual.tests.ts +++ b/packages/math-extras/test/floatEqual.tests.ts @@ -1,15 +1,14 @@ -import { expect } from 'chai'; import { floatEqual } from '@pixi/math-extras'; -describe('floatEqual', function () +describe('floatEqual', () => { it('should return true if the difference between values is less than epsilon', - function () + () => { // 0.1 + 0.2 = 0.3 is the common floating point pitfall. - expect(floatEqual(0.1 + 0.2, 0.3)).to.equal(true); + expect(floatEqual(0.1 + 0.2, 0.3)).toEqual(true); // now let's make it false - expect(floatEqual(0.1 + 0.2 + 0.00001, 0.3)).to.equal(false); + expect(floatEqual(0.1 + 0.2 + 0.00001, 0.3)).toEqual(false); }); }); diff --git a/packages/math-extras/test/lineIntersection.tests.ts b/packages/math-extras/test/lineIntersection.tests.ts index 4f90b40fd37..964bf1342b7 100644 --- a/packages/math-extras/test/lineIntersection.tests.ts +++ b/packages/math-extras/test/lineIntersection.tests.ts @@ -1,11 +1,10 @@ -import { Point } from '@pixi/math'; +import { Point } from '@pixi/core'; import { lineIntersection } from '@pixi/math-extras'; -import { expect } from 'chai'; -describe('lineIntersection', function () +describe('lineIntersection', () => { it('should return the point where the lines intersect', - function () + () => { const aStart = new Point(1, 2); const aEnd = new Point(3, 4); @@ -14,12 +13,12 @@ describe('lineIntersection', function () const intersect = lineIntersection(aStart, aEnd, bStart, bEnd); - expect(intersect.x).to.equal(6.25); - expect(intersect.y).to.equal(7.25); + expect(intersect.x).toEqual(6.25); + expect(intersect.y).toEqual(7.25); }); it('should return NaN if the lines are parallel', - function () + () => { const aStart = new Point(1, 2); const aEnd = new Point(3, 4); @@ -28,10 +27,10 @@ describe('lineIntersection', function () const parallel = lineIntersection(aStart, aEnd, parallelStart, parallelEnd); - expect(parallel.x).to.be.NaN; - expect(parallel.y).to.be.NaN; + expect(parallel.x).toBeNaN(); + expect(parallel.y).toBeNaN(); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const aStart = new Point(1, 2); @@ -41,10 +40,10 @@ describe('lineIntersection', function () const outValue = new Point(); const intersect = lineIntersection(aStart, aEnd, bStart, bEnd, outValue); - expect(intersect).to.equal(outValue); + expect(intersect).toEqual(outValue); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { const aStart = new Point(1, 2); const aEnd = new Point(3, 4); @@ -54,11 +53,11 @@ describe('lineIntersection', function () lineIntersection(aStart, aEnd, bStart, bEnd, outValue); - expect(outValue.x).to.equal(6.25); - expect(outValue.y).to.equal(7.25); + expect(outValue.x).toEqual(6.25); + expect(outValue.y).toEqual(7.25); }); - it('can take any IPointData as input', function () + it('can take any IPointData as input', () => { const aStart = { x: 1, y: 2 }; const aEnd = { x: 3, y: 4 }; @@ -67,7 +66,7 @@ describe('lineIntersection', function () const intersect = lineIntersection(aStart, aEnd, bStart, bEnd); - expect(intersect.x).to.equal(6.25); - expect(intersect.y).to.equal(7.25); + expect(intersect.x).toEqual(6.25); + expect(intersect.y).toEqual(7.25); }); }); diff --git a/packages/math-extras/test/segmentIntersection.tests.ts b/packages/math-extras/test/segmentIntersection.tests.ts index 2df1fdb6a92..4b646e72ce2 100644 --- a/packages/math-extras/test/segmentIntersection.tests.ts +++ b/packages/math-extras/test/segmentIntersection.tests.ts @@ -1,11 +1,11 @@ -import { Point } from '@pixi/math'; -import { expect } from 'chai'; +import { Point } from '@pixi/core'; + import { segmentIntersection } from '@pixi/math-extras'; -describe('segmentIntersection', function () +describe('segmentIntersection', () => { it('should return the point where the segments intersect', - function () + () => { const aStart = new Point(1, 2); const aEnd = new Point(11, 12); @@ -14,12 +14,12 @@ describe('segmentIntersection', function () const intersect = segmentIntersection(aStart, aEnd, bStart, bEnd); - expect(intersect.x).to.equal(6.25); - expect(intersect.y).to.equal(7.25); + expect(intersect.x).toEqual(6.25); + expect(intersect.y).toEqual(7.25); }); it('should return NaN if the segments are parallel', - function () + () => { const aStart = new Point(1, 2); const aEnd = new Point(11, 12); @@ -28,11 +28,11 @@ describe('segmentIntersection', function () const parallel = segmentIntersection(aStart, aEnd, parallelStart, parallelEnd); - expect(parallel.x).to.be.NaN; - expect(parallel.y).to.be.NaN; + expect(parallel.x).toBeNaN(); + expect(parallel.y).toBeNaN(); }); it('should return NaN if the segments dont intersect', - function () + () => { const aStart = new Point(1, 2); const aEnd = new Point(3, 4); @@ -41,10 +41,10 @@ describe('segmentIntersection', function () const parallel = segmentIntersection(aStart, aEnd, bStart, bEnd); - expect(parallel.x).to.be.NaN; - expect(parallel.y).to.be.NaN; + expect(parallel.x).toBeNaN(); + expect(parallel.y).toBeNaN(); }); - it('should return the same reference given', function () + it('should return the same reference given', () => { // Point const aStart = new Point(1, 2); @@ -54,10 +54,10 @@ describe('segmentIntersection', function () const outValue = new Point(); const intersect = segmentIntersection(aStart, aEnd, bStart, bEnd, outValue); - expect(intersect).to.equal(outValue); + expect(intersect).toEqual(outValue); }); - it('can output into any IPointData given', function () + it('can output into any IPointData given', () => { const aStart = new Point(1, 2); const aEnd = new Point(11, 12); @@ -67,11 +67,11 @@ describe('segmentIntersection', function () segmentIntersection(aStart, aEnd, bStart, bEnd, outValue); - expect(outValue.x).to.equal(6.25); - expect(outValue.y).to.equal(7.25); + expect(outValue.x).toEqual(6.25); + expect(outValue.y).toEqual(7.25); }); - it('can take any IPointData as input', function () + it('can take any IPointData as input', () => { const aStart = { x: 1, y: 2 }; const aEnd = { x: 11, y: 12 }; @@ -80,7 +80,7 @@ describe('segmentIntersection', function () const intersect = segmentIntersection(aStart, aEnd, bStart, bEnd); - expect(intersect.x).to.equal(6.25); - expect(intersect.y).to.equal(7.25); + expect(intersect.x).toEqual(6.25); + expect(intersect.y).toEqual(7.25); }); }); diff --git a/packages/math/package.json b/packages/math/package.json index bd4d4fe3a0b..7fa3fc530a3 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/math", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/math.js", - "module": "dist/esm/math.js", - "bundle": "dist/browser/math.js", + "module": "dist/esm/math.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/math.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/math.js" + } + } + }, "description": "Collection of math utilities", "author": "Mat Groves", "contributors": [ @@ -20,7 +32,6 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ] diff --git a/packages/math/src/IPoint.ts b/packages/math/src/IPoint.ts index 58900332c5e..8401b32558f 100644 --- a/packages/math/src/IPoint.ts +++ b/packages/math/src/IPoint.ts @@ -1,4 +1,4 @@ -import { IPointData } from './IPointData'; +import type { IPointData } from './IPointData'; export interface IPoint extends IPointData { @@ -17,7 +17,6 @@ export interface IPoint extends IPointData /** * Sets the point to a new x and y position. * If y is omitted, both x and y will be set to x. - * * @method set * @memberof PIXI.IPoint# * @param {number} [x=0] - position of the point on the x axis @@ -42,7 +41,6 @@ export interface IPoint extends IPointData /** * Returns true if the given point is equal to this point - * * @method equals * @memberof PIXI.IPoint# * @param {PIXI.IPointData} p - The point to check diff --git a/packages/math/src/Matrix.ts b/packages/math/src/Matrix.ts index 2301c8ddc46..0505720578f 100644 --- a/packages/math/src/Matrix.ts +++ b/packages/math/src/Matrix.ts @@ -13,7 +13,6 @@ import type { IPointData } from './IPointData'; * | b | d | ty| * | 0 | 0 | 1 | * ``` - * * @memberof PIXI */ export class Matrix @@ -36,7 +35,7 @@ export class Matrix /** @default 0 */ public ty: number; - public array: Float32Array|null = null; + public array: Float32Array | null = null; /** * @param a - x scale @@ -65,7 +64,6 @@ export class Matrix * d = array[4] * tx = array[2] * ty = array[5] - * * @param array - The array that the matrix will be populated from. */ fromArray(array: number[]): void @@ -80,14 +78,13 @@ export class Matrix /** * Sets the matrix properties. - * * @param a - Matrix component * @param b - Matrix component * @param c - Matrix component * @param d - Matrix component * @param tx - Matrix component * @param ty - Matrix component - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ set(a: number, b: number, c: number, d: number, tx: number, ty: number): this { @@ -103,10 +100,9 @@ export class Matrix /** * Creates an array from the current Matrix object. - * * @param transpose - Whether we need to transpose the matrix or not * @param [out=new Float32Array(9)] - If provided the array will be assigned to out - * @return The newly created array which contains the matrix + * @returns The newly created array which contains the matrix */ toArray(transpose: boolean, out?: Float32Array): Float32Array { @@ -148,10 +144,9 @@ export class Matrix /** * Get a new position with the current transformation applied. * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering) - * * @param pos - The origin * @param {PIXI.Point} [newPos] - The point that the new position is assigned to (allowed to be same as input) - * @return {PIXI.Point} The new point, transformed through this matrix + * @returns {PIXI.Point} The new point, transformed through this matrix */ apply

(pos: IPointData, newPos?: P): P { @@ -169,10 +164,9 @@ export class Matrix /** * Get a new position with the inverse of the current transformation applied. * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input) - * * @param pos - The origin * @param {PIXI.Point} [newPos] - The point that the new position is assigned to (allowed to be same as input) - * @return {PIXI.Point} The new point, inverse-transformed through this matrix + * @returns {PIXI.Point} The new point, inverse-transformed through this matrix */ applyInverse

(pos: IPointData, newPos?: P): P { @@ -191,10 +185,9 @@ export class Matrix /** * Translates the matrix on the x and y. - * * @param x - How much to translate x by * @param y - How much to translate y by - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ translate(x: number, y: number): this { @@ -206,10 +199,9 @@ export class Matrix /** * Applies a scale transformation to the matrix. - * * @param x - The amount to scale horizontally * @param y - The amount to scale vertically - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ scale(x: number, y: number): this { @@ -225,9 +217,8 @@ export class Matrix /** * Applies a rotation transformation to the matrix. - * * @param angle - The angle in radians. - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ rotate(angle: number): this { @@ -250,9 +241,8 @@ export class Matrix /** * Appends the given Matrix to this Matrix. - * * @param matrix - The matrix to append. - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ append(matrix: Matrix): this { @@ -274,7 +264,6 @@ export class Matrix /** * Sets the matrix based on all the available properties - * * @param x - Position on the x axis * @param y - Position on the y axis * @param pivotX - Pivot on the x axis @@ -284,7 +273,7 @@ export class Matrix * @param rotation - Rotation in radians * @param skewX - Skew on the x axis * @param skewY - Skew on the y axis - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ setTransform(x: number, y: number, pivotX: number, pivotY: number, scaleX: number, scaleY: number, rotation: number, skewX: number, skewY: number): this @@ -302,9 +291,8 @@ export class Matrix /** * Prepends the given Matrix to this Matrix. - * * @param matrix - The matrix to prepend - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ prepend(matrix: Matrix): this { @@ -329,9 +317,8 @@ export class Matrix /** * Decomposes the matrix (x, y, scaleX, scaleY, and rotation) and sets the properties on to a transform. - * * @param transform - The transform to apply the properties to. - * @return The transform with the newly applied properties + * @returns The transform with the newly applied properties */ decompose(transform: Transform): Transform { @@ -372,8 +359,7 @@ export class Matrix /** * Inverts this matrix - * - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ invert(): this { @@ -396,8 +382,7 @@ export class Matrix /** * Resets this Matrix to an identity (default) matrix. - * - * @return This matrix. Good for chaining method calls. + * @returns This matrix. Good for chaining method calls. */ identity(): this { @@ -413,8 +398,7 @@ export class Matrix /** * Creates a new Matrix object with the same values as this one. - * - * @return A copy of this matrix. Good for chaining method calls. + * @returns A copy of this matrix. Good for chaining method calls. */ clone(): Matrix { @@ -432,9 +416,8 @@ export class Matrix /** * Changes the values of the given matrix to be the same as the ones in this matrix - * * @param matrix - The matrix to copy to. - * @return The matrix given in parameter with its values updated. + * @returns The matrix given in parameter with its values updated. */ copyTo(matrix: Matrix): Matrix { @@ -450,9 +433,8 @@ export class Matrix /** * Changes the values of the matrix to be the same as the ones in given matrix - * * @param {PIXI.Matrix} matrix - The matrix to copy from. - * @return {PIXI.Matrix} this + * @returns {PIXI.Matrix} this */ copyFrom(matrix: Matrix): this { @@ -475,7 +457,6 @@ export class Matrix /** * A default (identity) matrix - * * @readonly */ static get IDENTITY(): Matrix @@ -485,7 +466,6 @@ export class Matrix /** * A temp matrix - * * @readonly */ static get TEMP_MATRIX(): Matrix diff --git a/packages/math/src/ObservablePoint.ts b/packages/math/src/ObservablePoint.ts index e8c9bb7beb6..1943eb5dfb9 100644 --- a/packages/math/src/ObservablePoint.ts +++ b/packages/math/src/ObservablePoint.ts @@ -8,7 +8,6 @@ export interface ObservablePoint extends GlobalMixins.Point, IPoint {} * the position on the horizontal axis and `y` represents the position on the vertical axis. * * An `ObservablePoint` is a point that triggers a callback when the point's position is changed. - * * @memberof PIXI */ export class ObservablePoint implements IPoint @@ -24,12 +23,11 @@ export class ObservablePoint implements IPoint /** * Creates a new `ObservablePoint` - * * @param cb - callback function triggered when `x` and/or `y` are changed * @param scope - owner of callback * @param {number} [x=0] - position of the point on the x axis * @param {number} [y=0] - position of the point on the y axis - */ + */ constructor(cb: (this: T) => any, scope: T, x = 0, y = 0) { this._x = x; @@ -43,11 +41,10 @@ export class ObservablePoint implements IPoint * Creates a clone of this point. * The callback and scope params can be overridden otherwise they will default * to the clone object's values. - * * @override * @param cb - The callback function triggered when `x` and/or `y` are changed * @param scope - The owner of the callback - * @return a copy of this observable point + * @returns a copy of this observable point */ clone(cb = this.cb, scope = this.scope): ObservablePoint { @@ -57,7 +54,6 @@ export class ObservablePoint implements IPoint /** * Sets the point to a new `x` and `y` position. * If `y` is omitted, both `x` and `y` will be set to `x`. - * * @param {number} [x=0] - position of the point on the x axis * @param {number} [y=x] - position of the point on the y axis * @returns The observable point instance itself @@ -76,7 +72,6 @@ export class ObservablePoint implements IPoint /** * Copies x and y from the given point (`p`) - * * @param p - The point to copy from. Can be any of type that is or extends `IPointData` * @returns The observable point instance itself */ @@ -94,7 +89,6 @@ export class ObservablePoint implements IPoint /** * Copies this point's x and y into that of the given point (`p`) - * * @param p - The point to copy to. Can be any of type that is or extends `IPointData` * @returns The point (`p`) with values updated */ @@ -107,7 +101,6 @@ export class ObservablePoint implements IPoint /** * Accepts another point (`p`) and returns `true` if the given point is equal to this point - * * @param p - The point to check * @returns Returns `true` if both `x` and `y` are equal */ diff --git a/packages/math/src/Point.ts b/packages/math/src/Point.ts index c18ae01c66d..d7c37a8dc89 100644 --- a/packages/math/src/Point.ts +++ b/packages/math/src/Point.ts @@ -6,10 +6,9 @@ export interface Point extends GlobalMixins.Point, IPoint {} /** * The Point object represents a location in a two-dimensional coordinate system, where `x` represents * the position on the horizontal axis and `y` represents the position on the vertical axis - * * @class * @memberof PIXI - * @implements IPoint + * @implements {IPoint} */ export class Point implements IPoint { @@ -18,7 +17,8 @@ export class Point implements IPoint /** Position of the point on the y axis */ public y = 0; - /** Creates a new `Point` + /** + * Creates a new `Point` * @param {number} [x=0] - position of the point on the x axis * @param {number} [y=0] - position of the point on the y axis */ @@ -28,7 +28,8 @@ export class Point implements IPoint this.y = y; } - /** Creates a clone of this point + /** + * Creates a clone of this point * @returns A clone of this point */ clone(): Point @@ -38,7 +39,6 @@ export class Point implements IPoint /** * Copies `x` and `y` from the given point into this point - * * @param p - The point to copy from * @returns The point instance itself */ @@ -51,7 +51,6 @@ export class Point implements IPoint /** * Copies this point's x and y into the given point (`p`). - * * @param p - The point to copy to. Can be any of type that is or extends `IPointData` * @returns The point (`p`) with values updated */ @@ -64,7 +63,6 @@ export class Point implements IPoint /** * Accepts another point (`p`) and returns `true` if the given point is equal to this point - * * @param p - The point to check * @returns Returns `true` if both `x` and `y` are equal */ @@ -76,7 +74,6 @@ export class Point implements IPoint /** * Sets the point to a new `x` and `y` position. * If `y` is omitted, both `x` and `y` will be set to `x`. - * * @param {number} [x=0] - position of the point on the `x` axis * @param {number} [y=x] - position of the point on the `y` axis * @returns The point instance itself diff --git a/packages/math/src/Transform.ts b/packages/math/src/Transform.ts index a64d9ea50d9..5f0d2d84fe9 100644 --- a/packages/math/src/Transform.ts +++ b/packages/math/src/Transform.ts @@ -6,7 +6,6 @@ export interface Transform extends GlobalMixins.Transform {} /** * Transform that takes care about its versions. - * * @memberof PIXI */ export class Transform @@ -32,10 +31,7 @@ export class Transform /** The skew amount, on the x and y axis. */ public skew: ObservablePoint; - /** - * The locally unique ID of the parent's world transform - * used to calculate the current world transformation matrix. - */ + /** The locally unique ID of the parent's world transform used to calculate the current world transformation matrix. */ public _parentID: number; /** The locally unique ID of the world transform. */ @@ -71,10 +67,7 @@ export class Transform /** The locally unique ID of the local transform. */ protected _localID: number; - /** - * The locally unique ID of the local transform - * used to calculate the current local transformation matrix. - */ + /** The locally unique ID of the local transform used to calculate the current local transformation matrix. */ protected _currentLocalID: number; constructor() @@ -151,7 +144,6 @@ export class Transform /** * Updates the local and the world transformation matrices. - * * @param parentTransform - The parent transform */ updateTransform(parentTransform: Transform): void @@ -196,7 +188,6 @@ export class Transform /** * Decomposes a matrix and sets the transforms properties based on it. - * * @param matrix - The matrix to decompose */ setFromMatrix(matrix: Matrix): void diff --git a/packages/math/src/const.ts b/packages/math/src/const.ts index 6fcfbf8450d..46a9138e25c 100644 --- a/packages/math/src/const.ts +++ b/packages/math/src/const.ts @@ -1,6 +1,5 @@ /** * Two Pi. - * * @static * @member {number} * @memberof PIXI @@ -9,7 +8,6 @@ export const PI_2 = Math.PI * 2; /** * Conversion factor for converting radians to degrees. - * * @static * @member {number} RAD_TO_DEG * @memberof PIXI @@ -18,7 +16,6 @@ export const RAD_TO_DEG = 180 / Math.PI; /** * Conversion factor for converting degrees to radians. - * * @static * @member {number} * @memberof PIXI @@ -27,7 +24,6 @@ export const DEG_TO_RAD = Math.PI / 180; /** * Constants that identify shapes, mainly to prevent `instanceof` calls. - * * @static * @memberof PIXI * @enum {number} @@ -37,7 +33,9 @@ export const DEG_TO_RAD = Math.PI / 180; * @property {number} ELIP Ellipse * @property {number} RREC Rounded Rectangle */ -export enum SHAPES { +export enum SHAPES +// eslint-disable-next-line @typescript-eslint/indent +{ POLY = 0, RECT = 1, CIRC = 2, diff --git a/packages/math/src/groupD8.ts b/packages/math/src/groupD8.ts index b6911813299..392a750dfc1 100644 --- a/packages/math/src/groupD8.ts +++ b/packages/math/src/groupD8.ts @@ -19,16 +19,14 @@ const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1]; /** * [Cayley Table]{@link https://en.wikipedia.org/wiki/Cayley_table} * for the composition of each rotation in the dihederal group D8. - * - * @type number[][] + * @type {number[][]} * @private */ const rotationCayley: number[][] = []; /** * Matrices for each `GD8Symmetry` rotation. - * - * @type Matrix[] + * @type {PIXI.Matrix[]} * @private */ const rotationMatrices: Matrix[] = []; @@ -101,7 +99,6 @@ type GD8Symmetry = number; * * **Origin:**
* This is the small part of gameofbombs.com portal system. It works. - * * @see PIXI.groupD8.E * @see PIXI.groupD8.SE * @see PIXI.groupD8.S @@ -119,7 +116,6 @@ export const groupD8 = { * | Rotation | Direction | * |----------|-----------| * | 0° | East | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -129,7 +125,6 @@ export const groupD8 = { * | Rotation | Direction | * |----------|-----------| * | 45°↻ | Southeast | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -139,7 +134,6 @@ export const groupD8 = { * | Rotation | Direction | * |----------|-----------| * | 90°↻ | South | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -149,7 +143,6 @@ export const groupD8 = { * | Rotation | Direction | * |----------|-----------| * | 135°↻ | Southwest | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -159,7 +152,6 @@ export const groupD8 = { * | Rotation | Direction | * |----------|-----------| * | 180° | West | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -169,7 +161,6 @@ export const groupD8 = { * | Rotation | Direction | * |-------------|--------------| * | -135°/225°↻ | Northwest | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -179,7 +170,6 @@ export const groupD8 = { * | Rotation | Direction | * |-------------|--------------| * | -90°/270°↻ | North | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -189,7 +179,6 @@ export const groupD8 = { * | Rotation | Direction | * |-------------|--------------| * | -45°/315°↻ | Northeast | - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -197,7 +186,6 @@ export const groupD8 = { /** * Reflection about Y-axis. - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -205,7 +193,6 @@ export const groupD8 = { /** * Reflection about the main diagonal. - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -213,7 +200,6 @@ export const groupD8 = { /** * Reflection about X-axis. - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -221,7 +207,6 @@ export const groupD8 = { /** * Reflection about reverse diagonal. - * * @memberof PIXI.groupD8 * @constant {PIXI.GD8Symmetry} */ @@ -230,7 +215,7 @@ export const groupD8 = { /** * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. - * @return {PIXI.GD8Symmetry} The X-component of the U-axis + * @returns {PIXI.GD8Symmetry} The X-component of the U-axis * after rotating the axes. */ uX: (ind: GD8Symmetry): GD8Symmetry => ux[ind], @@ -238,7 +223,7 @@ export const groupD8 = { /** * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. - * @return {PIXI.GD8Symmetry} The Y-component of the U-axis + * @returns {PIXI.GD8Symmetry} The Y-component of the U-axis * after rotating the axes. */ uY: (ind: GD8Symmetry): GD8Symmetry => uy[ind], @@ -246,7 +231,7 @@ export const groupD8 = { /** * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. - * @return {PIXI.GD8Symmetry} The X-component of the V-axis + * @returns {PIXI.GD8Symmetry} The X-component of the V-axis * after rotating the axes. */ vX: (ind: GD8Symmetry): GD8Symmetry => vx[ind], @@ -254,7 +239,7 @@ export const groupD8 = { /** * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. - * @return {PIXI.GD8Symmetry} The Y-component of the V-axis + * @returns {PIXI.GD8Symmetry} The Y-component of the V-axis * after rotating the axes. */ vY: (ind: GD8Symmetry): GD8Symmetry => vy[ind], @@ -264,7 +249,7 @@ export const groupD8 = { * @param {PIXI.GD8Symmetry} rotation - symmetry whose opposite * is needed. Only rotations have opposite symmetries while * reflections don't. - * @return {PIXI.GD8Symmetry} The opposite symmetry of `rotation` + * @returns {PIXI.GD8Symmetry} The opposite symmetry of `rotation` */ inv: (rotation: GD8Symmetry): GD8Symmetry => { @@ -298,7 +283,7 @@ export const groupD8 = { * is the row in the above cayley table. * @param {PIXI.GD8Symmetry} rotationFirst - First operation, which * is the column in the above cayley table. - * @return {PIXI.GD8Symmetry} Composed operation + * @returns {PIXI.GD8Symmetry} Composed operation */ add: (rotationSecond: GD8Symmetry, rotationFirst: GD8Symmetry): GD8Symmetry => ( rotationCayley[rotationSecond][rotationFirst] @@ -306,11 +291,10 @@ export const groupD8 = { /** * Reverse of `add`. - * * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} rotationSecond - Second operation * @param {PIXI.GD8Symmetry} rotationFirst - First operation - * @return {PIXI.GD8Symmetry} Result + * @returns {PIXI.GD8Symmetry} Result */ sub: (rotationSecond: GD8Symmetry, rotationFirst: GD8Symmetry): GD8Symmetry => ( rotationCayley[rotationSecond][groupD8.inv(rotationFirst)] @@ -319,7 +303,6 @@ export const groupD8 = { /** * Adds 180 degrees to rotation, which is a commutative * operation. - * * @memberof PIXI.groupD8 * @param {number} rotation - The number to rotate. * @returns {number} Rotated number @@ -329,7 +312,6 @@ export const groupD8 = { /** * Checks if the rotation angle is vertical, i.e. south * or north. It doesn't work for reflections. - * * @memberof PIXI.groupD8 * @param {PIXI.GD8Symmetry} rotation - The number to check. * @returns {boolean} Whether or not the direction is vertical @@ -339,11 +321,10 @@ export const groupD8 = { /** * Approximates the vector `V(dx,dy)` into one of the * eight directions provided by `groupD8`. - * * @memberof PIXI.groupD8 * @param {number} dx - X-component of the vector * @param {number} dy - Y-component of the vector - * @return {PIXI.GD8Symmetry} Approximation of the vector into + * @returns {PIXI.GD8Symmetry} Approximation of the vector into * one of the eight symmetries. */ byDirection: (dx: number, dy: number): GD8Symmetry => @@ -385,7 +366,6 @@ export const groupD8 = { /** * Helps sprite to compensate texture packer rotation. - * * @memberof PIXI.groupD8 * @param {PIXI.Matrix} matrix - sprite world matrix * @param {PIXI.GD8Symmetry} rotation - The rotation factor to use. diff --git a/packages/math/src/shapes/Circle.ts b/packages/math/src/shapes/Circle.ts index 352bf9bb377..e0fac482363 100644 --- a/packages/math/src/shapes/Circle.ts +++ b/packages/math/src/shapes/Circle.ts @@ -3,7 +3,6 @@ import { Rectangle } from './Rectangle'; /** * The Circle object is used to help draw graphics and can also be used to specify a hit area for displayObjects. - * * @memberof PIXI */ export class Circle @@ -19,7 +18,6 @@ export class Circle /** * The type of the object, mainly used to avoid `instanceof` checks - * * @default PIXI.SHAPES.CIRC * @see PIXI.SHAPES */ @@ -41,8 +39,7 @@ export class Circle /** * Creates a clone of this Circle instance - * - * @return A copy of the Circle + * @returns A copy of the Circle */ clone(): Circle { @@ -51,10 +48,9 @@ export class Circle /** * Checks whether the x and y coordinates given are contained within this circle - * * @param x - The X coordinate of the point to test * @param y - The Y coordinate of the point to test - * @return Whether the x/y coordinates are within this Circle + * @returns Whether the x/y coordinates are within this Circle */ contains(x: number, y: number): boolean { @@ -74,10 +70,9 @@ export class Circle } /** - * Returns the framing rectangle of the circle as a Rectangle object - * - * @return The framing rectangle - */ + * Returns the framing rectangle of the circle as a Rectangle object + * @returns The framing rectangle + */ getBounds(): Rectangle { return new Rectangle(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2); diff --git a/packages/math/src/shapes/Ellipse.ts b/packages/math/src/shapes/Ellipse.ts index 06310f3cb8c..2915700f300 100644 --- a/packages/math/src/shapes/Ellipse.ts +++ b/packages/math/src/shapes/Ellipse.ts @@ -3,7 +3,6 @@ import { SHAPES } from '../const'; /** * The Ellipse object is used to help draw graphics and can also be used to specify a hit area for displayObjects. - * * @memberof PIXI */ export class Ellipse @@ -22,7 +21,6 @@ export class Ellipse /** * The type of the object, mainly used to avoid `instanceof` checks - * * @default PIXI.SHAPES.ELIP * @see PIXI.SHAPES */ @@ -46,8 +44,7 @@ export class Ellipse /** * Creates a clone of this Ellipse instance - * - * @return {PIXI.Ellipse} A copy of the ellipse + * @returns {PIXI.Ellipse} A copy of the ellipse */ clone(): Ellipse { @@ -56,10 +53,9 @@ export class Ellipse /** * Checks whether the x and y coordinates given are contained within this ellipse - * * @param x - The X coordinate of the point to test * @param y - The Y coordinate of the point to test - * @return Whether the x/y coords are within this ellipse + * @returns Whether the x/y coords are within this ellipse */ contains(x: number, y: number): boolean { @@ -80,8 +76,7 @@ export class Ellipse /** * Returns the framing rectangle of the ellipse as a Rectangle object - * - * @return The framing rectangle + * @returns The framing rectangle */ getBounds(): Rectangle { diff --git a/packages/math/src/shapes/Polygon.ts b/packages/math/src/shapes/Polygon.ts index b36bdc01e63..dc83538480f 100644 --- a/packages/math/src/shapes/Polygon.ts +++ b/packages/math/src/shapes/Polygon.ts @@ -3,7 +3,6 @@ import type { IPointData } from '../IPointData'; /** * A class to define a shape via user defined coordinates. - * * @memberof PIXI */ export class Polygon @@ -16,14 +15,13 @@ export class Polygon /** * The type of the object, mainly used to avoid `instanceof` checks - * * @default PIXI.SHAPES.POLY * @see PIXI.SHAPES */ public readonly type: SHAPES.POLY; - constructor(points: IPointData[]|number[]); - constructor(...points: IPointData[]|number[]); + constructor(points: IPointData[] | number[]); + constructor(...points: IPointData[] | number[]); /** * @param {PIXI.IPointData[]|number[]} points - This can be an array of Points @@ -34,7 +32,7 @@ export class Polygon */ constructor(...points: any[]) { - let flat: IPointData[]|number[] = Array.isArray(points[0]) ? points[0] : points; + let flat: IPointData[] | number[] = Array.isArray(points[0]) ? points[0] : points; // if this is an array of points, convert it to a flat array of numbers if (typeof flat[0] !== 'number') @@ -56,8 +54,7 @@ export class Polygon /** * Creates a clone of this polygon. - * - * @return - A copy of the polygon. + * @returns - A copy of the polygon. */ clone(): Polygon { @@ -71,10 +68,9 @@ export class Polygon /** * Checks whether the x and y coordinates passed to this function are contained within this polygon. - * * @param x - The X coordinate of the point to test. * @param y - The Y coordinate of the point to test. - * @return - Whether the x/y coordinates are within this polygon. + * @returns - Whether the x/y coordinates are within this polygon. */ contains(x: number, y: number): boolean { diff --git a/packages/math/src/shapes/Rectangle.ts b/packages/math/src/shapes/Rectangle.ts index bb570f97826..ee68d80e3a4 100644 --- a/packages/math/src/shapes/Rectangle.ts +++ b/packages/math/src/shapes/Rectangle.ts @@ -1,5 +1,5 @@ import { SHAPES } from '../const'; -import { Matrix } from '../Matrix'; +import type { Matrix } from '../Matrix'; import { Point } from '../Point'; const tempPoints = [new Point(), new Point(), new Point(), new Point()]; @@ -9,15 +9,15 @@ export interface Rectangle extends GlobalMixins.Rectangle {} /** * Size object, contains width and height - * * @memberof PIXI * @typedef {object} ISize + * @property {number} width - Width component + * @property {number} height - Height component */ /** * Rectangle object is an area defined by its position, as indicated by its top-left corner * point (x, y) and by its width and its height. - * * @memberof PIXI */ export class Rectangle @@ -46,7 +46,7 @@ export class Rectangle * @param width - The overall width of the rectangle * @param height - The overall height of the rectangle */ - constructor(x = 0, y = 0, width = 0, height = 0) + constructor(x: string | number = 0, y: string | number = 0, width: string | number = 0, height: string | number = 0) { this.x = Number(x); this.y = Number(y); @@ -87,8 +87,7 @@ export class Rectangle /** * Creates a clone of this Rectangle - * - * @return a copy of the rectangle + * @returns a copy of the rectangle */ clone(): Rectangle { @@ -97,9 +96,8 @@ export class Rectangle /** * Copies another rectangle to this one. - * * @param rectangle - The rectangle to copy from. - * @return Returns itself. + * @returns Returns itself. */ copyFrom(rectangle: Rectangle): Rectangle { @@ -113,9 +111,8 @@ export class Rectangle /** * Copies this rectangle to another one. - * * @param rectangle - The rectangle to copy to. - * @return Returns given parameter. + * @returns Returns given parameter. */ copyTo(rectangle: Rectangle): Rectangle { @@ -129,10 +126,9 @@ export class Rectangle /** * Checks whether the x and y coordinates given are contained within this Rectangle - * * @param x - The X coordinate of the point to test * @param y - The Y coordinate of the point to test - * @return Whether the x/y coordinates are within this Rectangle + * @returns Whether the x/y coordinates are within this Rectangle */ contains(x: number, y: number): boolean { @@ -157,7 +153,6 @@ export class Rectangle * Returns true only if the area of the intersection is >0, this means that Rectangles * sharing a side are not overlapping. Another side effect is that an arealess rectangle * (width or height equal to zero) can't intersect any other rectangle. - * * @param {Rectangle} other - The Rectangle to intersect with `this`. * @param {Matrix} transform - The transformation matrix of `other`. * @returns {boolean} A value of `true` if the transformed `other` Rectangle intersects with `this`; otherwise `false`. @@ -252,10 +247,9 @@ export class Rectangle /** * Pads the rectangle making it grow in all directions. * If paddingY is omitted, both paddingX and paddingY will be set to paddingX. - * * @param paddingX - The horizontal padding amount. * @param paddingY - The vertical padding amount. - * @return Returns itself. + * @returns Returns itself. */ pad(paddingX = 0, paddingY = paddingX): this { @@ -270,9 +264,8 @@ export class Rectangle /** * Fits this rectangle around the passed one. - * * @param rectangle - The rectangle to fit. - * @return Returns itself. + * @returns Returns itself. */ fit(rectangle: Rectangle): this { @@ -291,10 +284,9 @@ export class Rectangle /** * Enlarges rectangle that way its corners lie on grid - * * @param resolution - resolution * @param eps - precision - * @return Returns itself. + * @returns Returns itself. */ ceil(resolution = 1, eps = 0.001): this { @@ -312,9 +304,8 @@ export class Rectangle /** * Enlarges this rectangle to include the passed rectangle. - * * @param rectangle - The rectangle to include. - * @return Returns itself. + * @returns Returns itself. */ enlarge(rectangle: Rectangle): this { diff --git a/packages/math/src/shapes/RoundedRectangle.ts b/packages/math/src/shapes/RoundedRectangle.ts index a569b2a9687..cbcf73f259c 100644 --- a/packages/math/src/shapes/RoundedRectangle.ts +++ b/packages/math/src/shapes/RoundedRectangle.ts @@ -3,7 +3,6 @@ import { SHAPES } from '../const'; /** * The Rounded Rectangle object is an area that has nice rounded corners, as indicated by its * top-left corner point (x, y) and by its width and its height and its radius. - * * @memberof PIXI */ export class RoundedRectangle @@ -25,7 +24,6 @@ export class RoundedRectangle /** * The type of the object, mainly used to avoid `instanceof` checks - * * @default PIXI.SHAPES.RREC * @see PIXI.SHAPES */ @@ -50,8 +48,7 @@ export class RoundedRectangle /** * Creates a clone of this Rounded Rectangle. - * - * @return - A copy of the rounded rectangle. + * @returns - A copy of the rounded rectangle. */ clone(): RoundedRectangle { @@ -60,10 +57,9 @@ export class RoundedRectangle /** * Checks whether the x and y coordinates given are contained within this Rounded Rectangle - * * @param x - The X coordinate of the point to test. * @param y - The Y coordinate of the point to test. - * @return - Whether the x/y coordinates are within this Rounded Rectangle. + * @returns - Whether the x/y coordinates are within this Rounded Rectangle. */ contains(x: number, y: number): boolean { diff --git a/packages/math/test/Circle.tests.ts b/packages/math/test/Circle.tests.ts index c6f50c7bd8e..4220bd13910 100644 --- a/packages/math/test/Circle.tests.ts +++ b/packages/math/test/Circle.tests.ts @@ -1,73 +1,72 @@ import { Circle } from '@pixi/math'; -import { expect } from 'chai'; -describe('Circle', function () +describe('Circle', () => { - it('should create a new circle', function () + it('should create a new circle', () => { const circ1 = new Circle(); - expect(circ1.x).to.equal(0); - expect(circ1.y).to.equal(0); - expect(circ1.radius).to.equal(0); + expect(circ1.x).toEqual(0); + expect(circ1.y).toEqual(0); + expect(circ1.radius).toEqual(0); const circ2 = new Circle(10, 10, 5); - expect(circ2.x).to.equal(10); - expect(circ2.y).to.equal(10); - expect(circ2.radius).to.equal(5); + expect(circ2.x).toEqual(10); + expect(circ2.y).toEqual(10); + expect(circ2.radius).toEqual(5); }); - it('should clone a new circle', function () + it('should clone a new circle', () => { const circ1 = new Circle(10, 10, 5); - expect(circ1.x).to.equal(10); - expect(circ1.y).to.equal(10); - expect(circ1.radius).to.equal(5); + expect(circ1.x).toEqual(10); + expect(circ1.y).toEqual(10); + expect(circ1.radius).toEqual(5); const circ2 = circ1.clone(); - expect(circ2.x).to.equal(10); - expect(circ2.y).to.equal(10); - expect(circ2.radius).to.equal(5); - expect(circ1).to.not.equal(circ2); + expect(circ2.x).toEqual(10); + expect(circ2.y).toEqual(10); + expect(circ2.radius).toEqual(5); + expect(circ1).not.toBe(circ2); }); - it('should check if point is within circle', function () + it('should check if point is within circle', () => { const circ1 = new Circle(10, 10, 5); - expect(circ1.contains(10, 10)).to.be.true; - expect(circ1.contains(10, 15)).to.be.true; - expect(circ1.contains(15, 10)).to.be.true; - expect(circ1.contains(5, 10)).to.be.true; - expect(circ1.contains(15, 10)).to.be.true; + expect(circ1.contains(10, 10)).toBe(true); + expect(circ1.contains(10, 15)).toBe(true); + expect(circ1.contains(15, 10)).toBe(true); + expect(circ1.contains(5, 10)).toBe(true); + expect(circ1.contains(15, 10)).toBe(true); - expect(circ1.contains(6, 7)).to.be.true; - expect(circ1.contains(7, 6)).to.be.true; - expect(circ1.contains(7, 7)).to.be.true; - expect(circ1.contains(13, 14)).to.be.true; - expect(circ1.contains(14, 13)).to.be.true; + expect(circ1.contains(6, 7)).toBe(true); + expect(circ1.contains(7, 6)).toBe(true); + expect(circ1.contains(7, 7)).toBe(true); + expect(circ1.contains(13, 14)).toBe(true); + expect(circ1.contains(14, 13)).toBe(true); - expect(circ1.contains(14, 14)).to.be.false; - expect(circ1.contains(10, 16)).to.be.false; - expect(circ1.contains(11, 15)).to.be.false; - expect(circ1.contains(0, 0)).to.be.false; + expect(circ1.contains(14, 14)).toBe(false); + expect(circ1.contains(10, 16)).toBe(false); + expect(circ1.contains(11, 15)).toBe(false); + expect(circ1.contains(0, 0)).toBe(false); const circ2 = new Circle(10, 10, 0); - expect(circ2.contains(10, 10)).to.be.false; + expect(circ2.contains(10, 10)).toBe(false); }); - it('should return framing rectangle', function () + it('should return framing rectangle', () => { const circ1 = new Circle(10, 10, 5); const rect1 = circ1.getBounds(); - expect(rect1.left).to.equal(5); - expect(rect1.top).to.equal(5); - expect(rect1.right).to.equal(15); - expect(rect1.bottom).to.equal(15); + expect(rect1.left).toEqual(5); + expect(rect1.top).toEqual(5); + expect(rect1.right).toEqual(15); + expect(rect1.bottom).toEqual(15); }); }); diff --git a/packages/math/test/Ellipse.tests.ts b/packages/math/test/Ellipse.tests.ts index ff63e7b0754..afbb0398c0e 100644 --- a/packages/math/test/Ellipse.tests.ts +++ b/packages/math/test/Ellipse.tests.ts @@ -1,76 +1,75 @@ import { Ellipse } from '@pixi/math'; -import { expect } from 'chai'; -describe('Ellipse', function () +describe('Ellipse', () => { - it('should create a new ellipse', function () + it('should create a new ellipse', () => { const ellipse1 = new Ellipse(); - expect(ellipse1.x).to.equal(0); - expect(ellipse1.y).to.equal(0); - expect(ellipse1.width).to.equal(0); - expect(ellipse1.height).to.equal(0); + expect(ellipse1.x).toEqual(0); + expect(ellipse1.y).toEqual(0); + expect(ellipse1.width).toEqual(0); + expect(ellipse1.height).toEqual(0); const ellipse2 = new Ellipse(10, 10, 5, 5); - expect(ellipse2.x).to.equal(10); - expect(ellipse2.y).to.equal(10); - expect(ellipse2.width).to.equal(5); - expect(ellipse2.height).to.equal(5); + expect(ellipse2.x).toEqual(10); + expect(ellipse2.y).toEqual(10); + expect(ellipse2.width).toEqual(5); + expect(ellipse2.height).toEqual(5); }); - it('should clone a new ellipse', function () + it('should clone a new ellipse', () => { const ellipse1 = new Ellipse(10, 10, 5, 5); - expect(ellipse1.x).to.equal(10); - expect(ellipse1.y).to.equal(10); - expect(ellipse1.width).to.equal(5); - expect(ellipse1.height).to.equal(5); + expect(ellipse1.x).toEqual(10); + expect(ellipse1.y).toEqual(10); + expect(ellipse1.width).toEqual(5); + expect(ellipse1.height).toEqual(5); const ellipse2 = ellipse1.clone(); - expect(ellipse2.x).to.equal(10); - expect(ellipse2.y).to.equal(10); - expect(ellipse2.width).to.equal(5); - expect(ellipse2.height).to.equal(5); + expect(ellipse2.x).toEqual(10); + expect(ellipse2.y).toEqual(10); + expect(ellipse2.width).toEqual(5); + expect(ellipse2.height).toEqual(5); }); - it('should check if point is within ellipse', function () + it('should check if point is within ellipse', () => { const ellipse1 = new Ellipse(10, 10, 5, 5); - expect(ellipse1.contains(10, 10)).to.be.true; - expect(ellipse1.contains(10, 15)).to.be.true; - expect(ellipse1.contains(15, 10)).to.be.true; - expect(ellipse1.contains(5, 10)).to.be.true; - expect(ellipse1.contains(15, 10)).to.be.true; + expect(ellipse1.contains(10, 10)).toBe(true); + expect(ellipse1.contains(10, 15)).toBe(true); + expect(ellipse1.contains(15, 10)).toBe(true); + expect(ellipse1.contains(5, 10)).toBe(true); + expect(ellipse1.contains(15, 10)).toBe(true); - expect(ellipse1.contains(6, 7)).to.be.true; - expect(ellipse1.contains(7, 6)).to.be.true; - expect(ellipse1.contains(7, 7)).to.be.true; - expect(ellipse1.contains(13, 14)).to.be.true; - expect(ellipse1.contains(14, 13)).to.be.true; + expect(ellipse1.contains(6, 7)).toBe(true); + expect(ellipse1.contains(7, 6)).toBe(true); + expect(ellipse1.contains(7, 7)).toBe(true); + expect(ellipse1.contains(13, 14)).toBe(true); + expect(ellipse1.contains(14, 13)).toBe(true); - expect(ellipse1.contains(14, 14)).to.be.false; - expect(ellipse1.contains(10, 16)).to.be.false; - expect(ellipse1.contains(11, 15)).to.be.false; - expect(ellipse1.contains(0, 0)).to.be.false; + expect(ellipse1.contains(14, 14)).toBe(false); + expect(ellipse1.contains(10, 16)).toBe(false); + expect(ellipse1.contains(11, 15)).toBe(false); + expect(ellipse1.contains(0, 0)).toBe(false); const ellipse2 = new Ellipse(10, 10, 0, 0); - expect(ellipse2.contains(10, 10)).to.be.false; + expect(ellipse2.contains(10, 10)).toBe(false); }); - it('should return framing rectangle', function () + it('should return framing rectangle', () => { const ellipse1 = new Ellipse(10, 10, 5, 5); const rect1 = ellipse1.getBounds(); - expect(rect1.left).to.equal(5); - expect(rect1.top).to.equal(5); - expect(rect1.right).to.equal(10); - expect(rect1.bottom).to.equal(10); + expect(rect1.left).toEqual(5); + expect(rect1.top).toEqual(5); + expect(rect1.right).toEqual(10); + expect(rect1.bottom).toEqual(10); }); }); diff --git a/packages/math/test/Matrix.tests.ts b/packages/math/test/Matrix.tests.ts index 56e3f944f51..2df38f76395 100644 --- a/packages/math/test/Matrix.tests.ts +++ b/packages/math/test/Matrix.tests.ts @@ -1,100 +1,100 @@ import { Matrix, Transform } from '@pixi/math'; -import { expect } from 'chai'; -describe('Matrix', function () +describe('Matrix', () => { - it('should create a new matrix', function () + it('should create a new matrix', () => { const matrix = new Matrix(); - expect(matrix.a).to.equal(1); - expect(matrix.b).to.equal(0); - expect(matrix.c).to.equal(0); - expect(matrix.d).to.equal(1); - expect(matrix.tx).to.equal(0); - expect(matrix.ty).to.equal(0); + expect(matrix.a).toEqual(1); + expect(matrix.b).toEqual(0); + expect(matrix.c).toEqual(0); + expect(matrix.d).toEqual(1); + expect(matrix.tx).toEqual(0); + expect(matrix.ty).toEqual(0); const input = [0, 1, 2, 3, 4, 5]; matrix.fromArray(input); - expect(matrix.a).to.equal(0); - expect(matrix.b).to.equal(1); - expect(matrix.c).to.equal(3); - expect(matrix.d).to.equal(4); - expect(matrix.tx).to.equal(2); - expect(matrix.ty).to.equal(5); + expect(matrix.a).toEqual(0); + expect(matrix.b).toEqual(1); + expect(matrix.c).toEqual(3); + expect(matrix.d).toEqual(4); + expect(matrix.tx).toEqual(2); + expect(matrix.ty).toEqual(5); let output = matrix.toArray(true); - expect(output.length).to.equal(9); - expect(output[0]).to.equal(0); - expect(output[1]).to.equal(1); - expect(output[3]).to.equal(3); - expect(output[4]).to.equal(4); - expect(output[6]).to.equal(2); - expect(output[7]).to.equal(5); + expect(output.length).toEqual(9); + expect(output[0]).toEqual(0); + expect(output[1]).toEqual(1); + expect(output[3]).toEqual(3); + expect(output[4]).toEqual(4); + expect(output[6]).toEqual(2); + expect(output[7]).toEqual(5); output = matrix.toArray(false); - expect(output.length).to.equal(9); - expect(output[0]).to.equal(0); - expect(output[1]).to.equal(3); - expect(output[2]).to.equal(2); - expect(output[3]).to.equal(1); - expect(output[4]).to.equal(4); - expect(output[5]).to.equal(5); + expect(output.length).toEqual(9); + expect(output[0]).toEqual(0); + expect(output[1]).toEqual(3); + expect(output[2]).toEqual(2); + expect(output[3]).toEqual(1); + expect(output[4]).toEqual(4); + expect(output[5]).toEqual(5); }); - it('should apply different transforms', function () + it('should apply different transforms', () => { const matrix = new Matrix(); matrix.translate(10, 20); matrix.translate(1, 2); - expect(matrix.tx).to.equal(11); - expect(matrix.ty).to.equal(22); + expect(matrix.tx).toEqual(11); + expect(matrix.ty).toEqual(22); matrix.scale(2, 4); - expect(matrix.a).to.equal(2); - expect(matrix.b).to.equal(0); - expect(matrix.c).to.equal(0); - expect(matrix.d).to.equal(4); - expect(matrix.tx).to.equal(22); - expect(matrix.ty).to.equal(88); + expect(matrix.a).toEqual(2); + expect(matrix.b).toEqual(0); + expect(matrix.c).toEqual(0); + expect(matrix.d).toEqual(4); + expect(matrix.tx).toEqual(22); + expect(matrix.ty).toEqual(88); const m2 = matrix.clone(); - expect(m2).to.not.equal(matrix); - expect(m2.a).to.equal(2); - expect(m2.b).to.equal(0); - expect(m2.c).to.equal(0); - expect(m2.d).to.equal(4); - expect(m2.tx).to.equal(22); - expect(m2.ty).to.equal(88); + expect(m2).not.toBe(matrix); + expect(m2.a).toEqual(2); + expect(m2.b).toEqual(0); + expect(m2.c).toEqual(0); + expect(m2.d).toEqual(4); + expect(m2.tx).toEqual(22); + expect(m2.ty).toEqual(88); matrix.setTransform(14, 15, 0, 0, 4, 2, 0, 0, 0); - expect(matrix.a).to.equal(4); - expect(matrix.b).to.equal(0); - expect(matrix.c).to.equal(0); - expect(matrix.d).to.equal(2); - expect(matrix.tx).to.equal(14); - expect(matrix.ty).to.equal(15); + expect(matrix.a).toEqual(4); + expect(matrix.b).toEqual(0); + // Object.is cant distinguish between 0 and -0 + expect(Math.abs(matrix.c)).toEqual(0); + expect(matrix.d).toEqual(2); + expect(matrix.tx).toEqual(14); + expect(matrix.ty).toEqual(15); }); - it('should allow rotatation', function () + it('should allow rotatation', () => { const matrix = new Matrix(); matrix.rotate(Math.PI); - expect(matrix.a).to.equal(-1); - expect(matrix.b).to.equal(Math.sin(Math.PI)); - expect(matrix.c).to.equal(-Math.sin(Math.PI)); - expect(matrix.d).to.equal(-1); + expect(matrix.a).toEqual(-1); + expect(matrix.b).toEqual(Math.sin(Math.PI)); + expect(matrix.c).toEqual(-Math.sin(Math.PI)); + expect(matrix.d).toEqual(-1); }); - it('should append matrix', function () + it('should append matrix', () => { const m1 = new Matrix(); const m2 = new Matrix(); @@ -104,11 +104,11 @@ describe('Matrix', function () m1.append(m2); - expect(m1.tx).to.equal(m2.tx); - expect(m1.ty).to.equal(m2.ty); + expect(m1.tx).toEqual(m2.tx); + expect(m1.ty).toEqual(m2.ty); }); - it('should prepend matrix', function () + it('should prepend matrix', () => { const m1 = new Matrix(); const m2 = new Matrix(); @@ -116,56 +116,56 @@ describe('Matrix', function () m2.set(2, 3, 4, 5, 100, 200); m1.prepend(m2); - expect(m1.a).to.equal(m2.a); - expect(m1.b).to.equal(m2.b); - expect(m1.c).to.equal(m2.c); - expect(m1.d).to.equal(m2.d); - expect(m1.tx).to.equal(m2.tx); - expect(m1.ty).to.equal(m2.ty); + expect(m1.a).toEqual(m2.a); + expect(m1.b).toEqual(m2.b); + expect(m1.c).toEqual(m2.c); + expect(m1.d).toEqual(m2.d); + expect(m1.tx).toEqual(m2.tx); + expect(m1.ty).toEqual(m2.ty); const m3 = new Matrix(); const m4 = new Matrix(); m3.prepend(m4); - expect(m3.a).to.equal(m4.a); - expect(m3.b).to.equal(m4.b); - expect(m3.c).to.equal(m4.c); - expect(m3.d).to.equal(m4.d); - expect(m3.tx).to.equal(m4.tx); - expect(m3.ty).to.equal(m4.ty); + expect(m3.a).toEqual(m4.a); + expect(m3.b).toEqual(m4.b); + expect(m3.c).toEqual(m4.c); + expect(m3.d).toEqual(m4.d); + expect(m3.tx).toEqual(m4.tx); + expect(m3.ty).toEqual(m4.ty); }); - it('should get IDENTITY and TEMP_MATRIX', function () + it('should get IDENTITY and TEMP_MATRIX', () => { - expect(Matrix.IDENTITY instanceof Matrix).to.be.true; - expect(Matrix.TEMP_MATRIX instanceof Matrix).to.be.true; + expect(Matrix.IDENTITY instanceof Matrix).toBe(true); + expect(Matrix.TEMP_MATRIX instanceof Matrix).toBe(true); }); - it('should reset matrix to default when identity() is called', function () + it('should reset matrix to default when identity() is called', () => { const matrix = new Matrix(); matrix.set(2, 3, 4, 5, 100, 200); - expect(matrix.a).to.equal(2); - expect(matrix.b).to.equal(3); - expect(matrix.c).to.equal(4); - expect(matrix.d).to.equal(5); - expect(matrix.tx).to.equal(100); - expect(matrix.ty).to.equal(200); + expect(matrix.a).toEqual(2); + expect(matrix.b).toEqual(3); + expect(matrix.c).toEqual(4); + expect(matrix.d).toEqual(5); + expect(matrix.tx).toEqual(100); + expect(matrix.ty).toEqual(200); matrix.identity(); - expect(matrix.a).to.equal(1); - expect(matrix.b).to.equal(0); - expect(matrix.c).to.equal(0); - expect(matrix.d).to.equal(1); - expect(matrix.tx).to.equal(0); - expect(matrix.ty).to.equal(0); + expect(matrix.a).toEqual(1); + expect(matrix.b).toEqual(0); + expect(matrix.c).toEqual(0); + expect(matrix.d).toEqual(1); + expect(matrix.tx).toEqual(0); + expect(matrix.ty).toEqual(0); }); - it('should have the same transform after decompose', function () + it('should have the same transform after decompose', () => { const matrix = new Matrix(); const transformInitial = new Transform(); @@ -182,7 +182,7 @@ describe('Matrix', function () transformInitial.skew.y = (Math.random() - 2) * Math.PI; matrix.setTransform( - transformInitial.x, transformInitial.y, + transformInitial.position.x, transformInitial.position.y, 0, 0, transformInitial.scale.x, transformInitial.scale.y, transformInitial.rotation, @@ -190,16 +190,19 @@ describe('Matrix', function () ); matrix.decompose(transformDecomposed); - expect(transformInitial.a).to.equal(transformDecomposed.a); - expect(transformInitial.b).to.equal(transformDecomposed.b); - expect(transformInitial.c).to.equal(transformDecomposed.c); - expect(transformInitial.d).to.equal(transformDecomposed.d); - expect(transformInitial.tx).to.equal(transformDecomposed.tx); - expect(transformInitial.ty).to.equal(transformDecomposed.ty); + transformInitial.updateLocalTransform(); + transformDecomposed.updateLocalTransform(); + + expect(transformInitial.localTransform.a).toBeCloseTo(transformDecomposed.localTransform.a, 0.0001); + expect(transformInitial.localTransform.b).toBeCloseTo(transformDecomposed.localTransform.b, 0.0001); + expect(transformInitial.localTransform.c).toBeCloseTo(transformDecomposed.localTransform.c, 0.0001); + expect(transformInitial.localTransform.d).toBeCloseTo(transformDecomposed.localTransform.d, 0.0001); + expect(transformInitial.localTransform.tx).toBeCloseTo(transformDecomposed.localTransform.tx, 0.0001); + expect(transformInitial.localTransform.ty).toBeCloseTo(transformDecomposed.localTransform.ty, 0.0001); } }); - it('should decompose corner case', function () + it('should decompose corner case', () => { const matrix = new Matrix(); const transform = new Transform(); @@ -212,15 +215,15 @@ describe('Matrix', function () matrix.decompose(transform); transform.updateLocalTransform(); - expect(result.a).to.closeTo(matrix.a, 0.001); - expect(result.b).to.closeTo(matrix.b, 0.001); - expect(result.c).to.closeTo(matrix.c, 0.001); - expect(result.d).to.closeTo(matrix.d, 0.001); + expect(result.a).toBeCloseTo(matrix.a, 0.001); + expect(result.b).toBeCloseTo(matrix.b, 0.001); + expect(result.c).toBeCloseTo(matrix.c, 0.001); + expect(result.d).toBeCloseTo(matrix.d, 0.001); }); - describe('decompose', function () + describe('decompose', () => { - it('should be the inverse of updateLocalTransform even when pivot is set', function () + it('should be the inverse of updateLocalTransform even when pivot is set', () => { const matrix = new Matrix(0.01, 0.04, 0.04, 0.1, 2, 2); const transform = new Transform(); @@ -232,12 +235,12 @@ describe('Matrix', function () const localTransform = transform.localTransform; - expect(localTransform.a).to.closeTo(matrix.a, 0.001); - expect(localTransform.b).to.closeTo(matrix.b, 0.001); - expect(localTransform.c).to.closeTo(matrix.c, 0.001); - expect(localTransform.d).to.closeTo(matrix.d, 0.001); - expect(localTransform.tx).to.closeTo(matrix.tx, 0.001); - expect(localTransform.ty).to.closeTo(matrix.ty, 0.001); + expect(localTransform.a).toBeCloseTo(matrix.a, 0.001); + expect(localTransform.b).toBeCloseTo(matrix.b, 0.001); + expect(localTransform.c).toBeCloseTo(matrix.c, 0.001); + expect(localTransform.d).toBeCloseTo(matrix.d, 0.001); + expect(localTransform.tx).toBeCloseTo(matrix.tx, 0.001); + expect(localTransform.ty).toBeCloseTo(matrix.ty, 0.001); }); }); }); diff --git a/packages/math/test/ObservablePoint.tests.ts b/packages/math/test/ObservablePoint.tests.ts index 07342a9dc75..cc0c58a6c5a 100644 --- a/packages/math/test/ObservablePoint.tests.ts +++ b/packages/math/test/ObservablePoint.tests.ts @@ -1,39 +1,37 @@ import { ObservablePoint } from '@pixi/math'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('ObservablePoint', function () +describe('ObservablePoint', () => { - it('should create a new observable point', function () + it('should create a new observable point', () => { - const cb = sinon.spy(); + const cb = jest.fn(); const pt = new ObservablePoint(cb, this); - expect(pt.x).to.equal(0); - expect(pt.y).to.equal(0); + expect(pt.x).toEqual(0); + expect(pt.y).toEqual(0); pt.set(2, 5); - expect(pt.x).to.equal(2); - expect(pt.y).to.equal(5); + expect(pt.x).toEqual(2); + expect(pt.y).toEqual(5); - expect(cb.called).to.be.true; + expect(cb).toBeCalled(); pt.set(2, 6); - expect(pt.x).to.equal(2); - expect(pt.y).to.equal(6); + expect(pt.x).toEqual(2); + expect(pt.y).toEqual(6); pt.set(2, 0); - expect(pt.x).to.equal(2); - expect(pt.y).to.equal(0); + expect(pt.x).toEqual(2); + expect(pt.y).toEqual(0); pt.set(); - expect(pt.x).to.equal(0); - expect(pt.y).to.equal(0); + expect(pt.x).toEqual(0); + expect(pt.y).toEqual(0); - expect(cb.callCount).to.equal(4); + expect(cb.mock.calls).toHaveLength(4); }); - it('should copy a new observable point', function () + it('should copy a new observable point', () => { function cb() { @@ -45,11 +43,11 @@ describe('ObservablePoint', function () const p3 = new ObservablePoint(cb, this, 5, 6); p1.copyFrom(p2); - expect(p1.x).to.equal(p2.x); - expect(p1.y).to.equal(p2.y); + expect(p1.x).toEqual(p2.x); + expect(p1.y).toEqual(p2.y); p1.copyFrom(p3); - expect(p1.y).to.equal(p3.y); + expect(p1.y).toEqual(p3.y); }); }); diff --git a/packages/math/test/Point.tests.ts b/packages/math/test/Point.tests.ts index 8470147fabb..f16fd62268c 100644 --- a/packages/math/test/Point.tests.ts +++ b/packages/math/test/Point.tests.ts @@ -1,56 +1,55 @@ import { Point } from '@pixi/math'; -import { expect } from 'chai'; -describe('Point', function () +describe('Point', () => { - it('should create a new point', function () + it('should create a new point', () => { const pt = new Point(); - expect(pt.x).to.equal(0); - expect(pt.y).to.equal(0); + expect(pt.x).toEqual(0); + expect(pt.y).toEqual(0); }); - it('should clone a new point', function () + it('should clone a new point', () => { const p1 = new Point(10, 20); - expect(p1.x).to.equal(10); - expect(p1.y).to.equal(20); + expect(p1.x).toEqual(10); + expect(p1.y).toEqual(20); const p2 = p1.clone(); - expect(p2.x).to.equal(10); - expect(p2.y).to.equal(20); - expect(p1).to.not.equal(p2); - expect(p1.equals(p2)).to.be.true; + expect(p2.x).toEqual(10); + expect(p2.y).toEqual(20); + expect(p1).not.toBe(p2); + expect(p1.equals(p2)).toBe(true); }); - it('should copy from one point to another', function () + it('should copy from one point to another', () => { const p1 = new Point(10, 20); const p2 = new Point(2, 5); p1.copyFrom(p2); - expect(p1.x).to.equal(2); - expect(p1.y).to.equal(5); + expect(p1.x).toEqual(2); + expect(p1.y).toEqual(5); }); - it('should set a new value', function () + it('should set a new value', () => { const p1 = new Point(10, 20); p1.set(); - expect(p1.x).to.equal(0); - expect(p1.y).to.equal(0); + expect(p1.x).toEqual(0); + expect(p1.y).toEqual(0); p1.set(1); - expect(p1.x).to.equal(1); - expect(p1.y).to.equal(1); + expect(p1.x).toEqual(1); + expect(p1.y).toEqual(1); p1.set(1, 0); - expect(p1.x).to.equal(1); - expect(p1.y).to.equal(0); + expect(p1.x).toEqual(1); + expect(p1.y).toEqual(0); }); }); diff --git a/packages/math/test/Polygon.tests.ts b/packages/math/test/Polygon.tests.ts index d3a5f0db228..ba74c00f44b 100644 --- a/packages/math/test/Polygon.tests.ts +++ b/packages/math/test/Polygon.tests.ts @@ -1,18 +1,17 @@ import { Polygon, Point } from '@pixi/math'; -import { expect } from 'chai'; -describe('Polygon', function () +describe('Polygon', () => { - describe('constructor', function () + describe('constructor', () => { - it('should accept a spread of values', function () + it('should accept a spread of values', () => { const polygon = new Polygon(0, 0, 10, 0, 0, 10); - expect(polygon.points.length).to.be.equals(6); + expect(polygon.points.length).toEqual(6); }); - it('should accept a spread of points', function () + it('should accept a spread of points', () => { const polygon = new Polygon( new Point(0, 0), @@ -20,17 +19,17 @@ describe('Polygon', function () new Point(0, 10) ); - expect(polygon.points.length).to.be.equals(6); + expect(polygon.points.length).toEqual(6); }); - it('should accept an array of values', function () + it('should accept an array of values', () => { const polygon = new Polygon([0, 0, 10, 0, 0, 10]); - expect(polygon.points.length).to.be.equals(6); + expect(polygon.points.length).toEqual(6); }); - it('should accept an array of points', function () + it('should accept an array of points', () => { const polygon = new Polygon([ new Point(0, 0), @@ -38,13 +37,13 @@ describe('Polygon', function () new Point(0, 10), ]); - expect(polygon.points.length).to.be.equals(6); + expect(polygon.points.length).toEqual(6); }); }); - describe('clone', function () + describe('clone', () => { - it('should create a copy', function () + it('should create a copy', () => { const polygon1 = new Polygon(0, 0, 10, 0, 0, 10); @@ -52,52 +51,51 @@ describe('Polygon', function () const polygon2 = polygon1.clone(); - expect(polygon1.points.length).to.be.equals(6); - expect(polygon1.points.length).to.be.equals(6); + expect(polygon1.points.length).toEqual(6); + expect(polygon1.points.length).toEqual(6); for (let i = 0; i < 6; i++) { - expect(polygon1.points[i]).to.be.equals(polygon2.points[i]); + expect(polygon1.points[i]).toEqual(polygon2.points[i]); } - expect(polygon1.closeStroke).to.be.equals(polygon2.closeStroke); + expect(polygon1.closeStroke).toEqual(polygon2.closeStroke); polygon2.points.push(0, 0); - expect(polygon1.points.length).to.be.equals(6); - expect(polygon2.points.length).to.be.equals(8); + expect(polygon1.points.length).toEqual(6); + expect(polygon2.points.length).toEqual(8); }); }); - describe('contains', function () + describe('contains', () => { - it('should include points inside', function () + it('should include points inside', () => { const polygon = new Polygon(0, 0, 10, 0, 10, 10, 0, 10, 0, 0); - expect(polygon.contains(1, 1)).to.be.true; - expect(polygon.contains(1, 9)).to.be.true; - expect(polygon.contains(9, 1)).to.be.true; - expect(polygon.contains(9, 9)).to.be.true; + expect(polygon.contains(1, 1)).toBe(true); + expect(polygon.contains(1, 9)).toBe(true); + expect(polygon.contains(9, 1)).toBe(true); + expect(polygon.contains(9, 9)).toBe(true); }); - it('should exclude bounds', function () + it('should exclude bounds', () => { const polygon = new Polygon(0, 0, 10, 0, 10, 10, 0, 10, 0, 0); - // expect(polygon.contains(0, 0)).to.be.false; // this currently returns true - expect(polygon.contains(0, 10)).to.be.false; - expect(polygon.contains(10, 0)).to.be.false; - expect(polygon.contains(10, 10)).to.be.false; + expect(polygon.contains(0, 10)).toBe(false); + expect(polygon.contains(10, 0)).toBe(false); + expect(polygon.contains(10, 10)).toBe(false); }); - it('should exclude points outside', function () + it('should exclude points outside', () => { const polygon = new Polygon(0, 0, 10, 0, 10, 10, 0, 10, 0, 0); - expect(polygon.contains(-1, -1)).to.be.false; - expect(polygon.contains(-1, 11)).to.be.false; - expect(polygon.contains(11, -1)).to.be.false; - expect(polygon.contains(11, 11)).to.be.false; + expect(polygon.contains(-1, -1)).toBe(false); + expect(polygon.contains(-1, 11)).toBe(false); + expect(polygon.contains(11, -1)).toBe(false); + expect(polygon.contains(11, 11)).toBe(false); }); }); }); diff --git a/packages/math/test/Rectangle.tests.ts b/packages/math/test/Rectangle.tests.ts index 0a51b09582e..c3b1570a436 100644 --- a/packages/math/test/Rectangle.tests.ts +++ b/packages/math/test/Rectangle.tests.ts @@ -1,203 +1,202 @@ import { Rectangle, Matrix } from '@pixi/math'; -import { expect } from 'chai'; -describe('Rectangle', function () +describe('Rectangle', () => { - it('should create a new rectangle', function () + it('should create a new rectangle', () => { const rect = new Rectangle(5, 5, 1, 1); - expect(rect.left).to.equal(5); - expect(rect.top).to.equal(5); - expect(rect.right).to.equal(6); - expect(rect.bottom).to.equal(6); + expect(rect.left).toEqual(5); + expect(rect.top).toEqual(5); + expect(rect.right).toEqual(6); + expect(rect.bottom).toEqual(6); }); - it('should cast quantities to number types', function () + it('should cast quantities to number types', () => { const rect = new Rectangle('5', '5', '1', '1'); - expect(rect.left).to.equal(5); - expect(rect.top).to.equal(5); - expect(rect.right).to.equal(6); - expect(rect.bottom).to.equal(6); + expect(rect.left).toEqual(5); + expect(rect.top).toEqual(5); + expect(rect.right).toEqual(6); + expect(rect.bottom).toEqual(6); }); - it('should clone a new rectangle', function () + it('should clone a new rectangle', () => { const rect1 = new Rectangle(10, 10, 10, 10); - expect(rect1.x).to.equal(10); - expect(rect1.y).to.equal(10); - expect(rect1.width).to.equal(10); - expect(rect1.height).to.equal(10); + expect(rect1.x).toEqual(10); + expect(rect1.y).toEqual(10); + expect(rect1.width).toEqual(10); + expect(rect1.height).toEqual(10); const rect2 = rect1.clone(); - expect(rect2.x).to.equal(10); - expect(rect2.y).to.equal(10); - expect(rect2.width).to.equal(10); - expect(rect2.height).to.equal(10); - expect(rect1).to.not.equal(rect2); + expect(rect2.x).toEqual(10); + expect(rect2.y).toEqual(10); + expect(rect2.width).toEqual(10); + expect(rect2.height).toEqual(10); + expect(rect1).not.toBe(rect2); }); - it('should copy from one rectangle to another', function () + it('should copy from one rectangle to another', () => { const rect1 = new Rectangle(10, 10, 10, 10); const rect2 = new Rectangle(2, 2, 5, 5); rect1.copyFrom(rect2); - expect(rect1.x).to.equal(2); - expect(rect1.y).to.equal(2); - expect(rect1.width).to.equal(5); - expect(rect1.height).to.equal(5); + expect(rect1.x).toEqual(2); + expect(rect1.y).toEqual(2); + expect(rect1.width).toEqual(5); + expect(rect1.height).toEqual(5); }); - it('should check if point is within rectangle', function () + it('should check if point is within rectangle', () => { const rect1 = new Rectangle(10, 10, 10, 10); - expect(rect1.contains(10, 10)).to.be.true; - expect(rect1.contains(10, 19)).to.be.true; - expect(rect1.contains(19, 10)).to.be.true; - expect(rect1.contains(15, 15)).to.be.true; - expect(rect1.contains(10, 9)).to.be.false; - expect(rect1.contains(9, 10)).to.be.false; - expect(rect1.contains(10, 20)).to.be.false; - expect(rect1.contains(20, 10)).to.be.false; - expect(rect1.contains(21, 21)).to.be.false; + expect(rect1.contains(10, 10)).toBe(true); + expect(rect1.contains(10, 19)).toBe(true); + expect(rect1.contains(19, 10)).toBe(true); + expect(rect1.contains(15, 15)).toBe(true); + expect(rect1.contains(10, 9)).toBe(false); + expect(rect1.contains(9, 10)).toBe(false); + expect(rect1.contains(10, 20)).toBe(false); + expect(rect1.contains(20, 10)).toBe(false); + expect(rect1.contains(21, 21)).toBe(false); const rect2 = new Rectangle(10, 10, 10, 0); - expect(rect2.contains(10, 10)).to.be.false; - expect(rect2.contains(20, 20)).to.be.false; - expect(rect2.contains(15, 15)).to.be.false; - expect(rect2.contains(10, 9)).to.be.false; - expect(rect2.contains(9, 10)).to.be.false; - expect(rect2.contains(21, 21)).to.be.false; + expect(rect2.contains(10, 10)).toBe(false); + expect(rect2.contains(20, 20)).toBe(false); + expect(rect2.contains(15, 15)).toBe(false); + expect(rect2.contains(10, 9)).toBe(false); + expect(rect2.contains(9, 10)).toBe(false); + expect(rect2.contains(21, 21)).toBe(false); }); - it('should enlarge rectangle', function () + it('should enlarge rectangle', () => { const rect1 = new Rectangle(10, 10, 10, 10); const rect2 = new Rectangle(15, 15, 10, 10); rect1.enlarge(rect2); - expect(rect1.left).to.equal(10); - expect(rect1.top).to.equal(10); - expect(rect1.right).to.equal(25); - expect(rect1.bottom).to.equal(25); + expect(rect1.left).toEqual(10); + expect(rect1.top).toEqual(10); + expect(rect1.right).toEqual(25); + expect(rect1.bottom).toEqual(25); const rect3 = new Rectangle(0, 0, 0, 0); const rect4 = new Rectangle(10, 10, 10, 10); rect4.enlarge(rect3); - expect(rect4.left).to.equal(0); - expect(rect4.top).to.equal(0); - expect(rect4.right).to.equal(20); - expect(rect4.bottom).to.equal(20); + expect(rect4.left).toEqual(0); + expect(rect4.top).toEqual(0); + expect(rect4.right).toEqual(20); + expect(rect4.bottom).toEqual(20); }); - it('should pad a rectangle', function () + it('should pad a rectangle', () => { // Pad with X & Y const rect = new Rectangle(10, 10, 10, 10); rect.pad(10, 10); - expect(rect.left).to.equal(0); - expect(rect.top).to.equal(0); - expect(rect.right).to.equal(30); - expect(rect.bottom).to.equal(30); + expect(rect.left).toEqual(0); + expect(rect.top).toEqual(0); + expect(rect.right).toEqual(30); + expect(rect.bottom).toEqual(30); // Pad with X const rect1 = new Rectangle(10, 10, 10, 10); rect1.pad(10); - expect(rect1.left).to.equal(0); - expect(rect1.top).to.equal(0); - expect(rect1.right).to.equal(30); - expect(rect1.bottom).to.equal(30); + expect(rect1.left).toEqual(0); + expect(rect1.top).toEqual(0); + expect(rect1.right).toEqual(30); + expect(rect1.bottom).toEqual(30); // Pad with nothing const rect2 = new Rectangle(10, 10, 10, 10); rect2.pad(); - expect(rect2.left).to.equal(10); - expect(rect2.top).to.equal(10); - expect(rect2.right).to.equal(20); - expect(rect2.bottom).to.equal(20); + expect(rect2.left).toEqual(10); + expect(rect2.top).toEqual(10); + expect(rect2.right).toEqual(20); + expect(rect2.bottom).toEqual(20); // Pad with Y const rect3 = new Rectangle(10, 10, 10, 10); rect3.pad(null, 10); - expect(rect3.left).to.equal(10); - expect(rect3.top).to.equal(0); - expect(rect3.right).to.equal(20); - expect(rect3.bottom).to.equal(30); + expect(rect3.left).toEqual(10); + expect(rect3.top).toEqual(0); + expect(rect3.right).toEqual(20); + expect(rect3.bottom).toEqual(30); }); - it('should fit a rectangle', function () + it('should fit a rectangle', () => { const rect1 = new Rectangle(0, 0, 10, 10); const rect2 = new Rectangle(-10, -10, 5, 5); rect2.fit(rect1); - expect(rect2.left).to.equal(0); - expect(rect2.top).to.equal(0); - expect(rect2.right).to.equal(0); - expect(rect2.bottom).to.equal(0); + expect(rect2.left).toEqual(0); + expect(rect2.top).toEqual(0); + expect(rect2.right).toEqual(0); + expect(rect2.bottom).toEqual(0); const rect3 = new Rectangle(0, 0, 20, 20); const rect4 = new Rectangle(10, 0, 20, 20); rect3.fit(rect4); - expect(rect3.left).to.equal(10); - expect(rect3.top).to.equal(0); - expect(rect3.right).to.equal(20); - expect(rect3.bottom).to.equal(20); + expect(rect3.left).toEqual(10); + expect(rect3.top).toEqual(0); + expect(rect3.right).toEqual(20); + expect(rect3.bottom).toEqual(20); const rect5 = new Rectangle(10, 10, 20, 25); const rect6 = new Rectangle(22, 24, 20, 20); rect5.fit(rect6); - expect(rect5.left).to.equal(22); - expect(rect5.top).to.equal(24); - expect(rect5.right).to.equal(30); - expect(rect5.bottom).to.equal(35); + expect(rect5.left).toEqual(22); + expect(rect5.top).toEqual(24); + expect(rect5.right).toEqual(30); + expect(rect5.bottom).toEqual(35); const rect7 = new Rectangle(11, 10, 20, 25); const rect8 = new Rectangle(10, 9, 13, 10); rect7.fit(rect8); - expect(rect7.left).to.equal(11); - expect(rect7.top).to.equal(10); - expect(rect7.right).to.equal(23); - expect(rect7.bottom).to.equal(19); + expect(rect7.left).toEqual(11); + expect(rect7.top).toEqual(10); + expect(rect7.right).toEqual(23); + expect(rect7.bottom).toEqual(19); }); - it('should generate an empty rectangle', function () + it('should generate an empty rectangle', () => { const rect = Rectangle.EMPTY; - expect(rect.left).to.equal(0); - expect(rect.top).to.equal(0); - expect(rect.right).to.equal(0); - expect(rect.bottom).to.equal(0); + expect(rect.left).toEqual(0); + expect(rect.top).toEqual(0); + expect(rect.right).toEqual(0); + expect(rect.bottom).toEqual(0); }); - it('should return true if the area of the intersection > 0', function () + it('should return true if the area of the intersection > 0', () => { /* ! SHARING A SIDE IS NOT INTERSECTING ! @@ -219,83 +218,83 @@ describe('Rectangle', function () const f = new Rectangle(150, 175, 0, 0); // e intersects a,b,c,d - expect(e.intersects(a)).to.equal(true); - expect(e.intersects(b)).to.equal(true); - expect(e.intersects(c)).to.equal(true); - expect(e.intersects(d)).to.equal(true); + expect(e.intersects(a)).toEqual(true); + expect(e.intersects(b)).toEqual(true); + expect(e.intersects(c)).toEqual(true); + expect(e.intersects(d)).toEqual(true); - expect(e.intersects(a, new Matrix())).to.equal(true); - expect(e.intersects(b, new Matrix())).to.equal(true); - expect(e.intersects(c, new Matrix())).to.equal(true); - expect(e.intersects(d, new Matrix())).to.equal(true); + expect(e.intersects(a, new Matrix())).toEqual(true); + expect(e.intersects(b, new Matrix())).toEqual(true); + expect(e.intersects(c, new Matrix())).toEqual(true); + expect(e.intersects(d, new Matrix())).toEqual(true); // works the other way arround - expect(a.intersects(e)).to.equal(true); - expect(b.intersects(e)).to.equal(true); - expect(c.intersects(e)).to.equal(true); - expect(d.intersects(e)).to.equal(true); + expect(a.intersects(e)).toEqual(true); + expect(b.intersects(e)).toEqual(true); + expect(c.intersects(e)).toEqual(true); + expect(d.intersects(e)).toEqual(true); - expect(a.intersects(e, new Matrix())).to.equal(true); - expect(b.intersects(e, new Matrix())).to.equal(true); - expect(c.intersects(e, new Matrix())).to.equal(true); - expect(d.intersects(e, new Matrix())).to.equal(true); + expect(a.intersects(e, new Matrix())).toEqual(true); + expect(b.intersects(e, new Matrix())).toEqual(true); + expect(c.intersects(e, new Matrix())).toEqual(true); + expect(d.intersects(e, new Matrix())).toEqual(true); // none of the other intersect (sharing a side it is NOT intersecting!) - expect(a.intersects(b)).to.equal(false); // share Y side - expect(b.intersects(d)).to.equal(false); // share X side - expect(c.intersects(b)).to.equal(false); // share single point + expect(a.intersects(b)).toEqual(false); // share Y side + expect(b.intersects(d)).toEqual(false); // share X side + expect(c.intersects(b)).toEqual(false); // share single point - expect(a.intersects(b, new Matrix())).to.equal(false); // share Y side - expect(b.intersects(d, new Matrix())).to.equal(false); // share X side - expect(c.intersects(b, new Matrix())).to.equal(false); // share single point + expect(a.intersects(b, new Matrix())).toEqual(false); // share Y side + expect(b.intersects(d, new Matrix())).toEqual(false); // share X side + expect(c.intersects(b, new Matrix())).toEqual(false); // share single point // Since F has no area, the intersection with D it's 0 so it's false. - expect(f.intersects(d)).to.equal(false); + expect(f.intersects(d)).toEqual(false); - expect(f.intersects(d, new Matrix())).to.equal(false); + expect(f.intersects(d, new Matrix())).toEqual(false); // Any rectangle with area intersects itself - expect(a.intersects(a.clone())).to.equal(true); - expect(b.intersects(b.clone())).to.equal(true); - expect(c.intersects(c.clone())).to.equal(true); - expect(d.intersects(d.clone())).to.equal(true); - expect(e.intersects(e.clone())).to.equal(true); - - expect(a.intersects(a.clone(), new Matrix())).to.equal(true); - expect(b.intersects(b.clone(), new Matrix())).to.equal(true); - expect(c.intersects(c.clone(), new Matrix())).to.equal(true); - expect(d.intersects(d.clone(), new Matrix())).to.equal(true); - expect(e.intersects(e.clone(), new Matrix())).to.equal(true); + expect(a.intersects(a.clone())).toEqual(true); + expect(b.intersects(b.clone())).toEqual(true); + expect(c.intersects(c.clone())).toEqual(true); + expect(d.intersects(d.clone())).toEqual(true); + expect(e.intersects(e.clone())).toEqual(true); + + expect(a.intersects(a.clone(), new Matrix())).toEqual(true); + expect(b.intersects(b.clone(), new Matrix())).toEqual(true); + expect(c.intersects(c.clone(), new Matrix())).toEqual(true); + expect(d.intersects(d.clone(), new Matrix())).toEqual(true); + expect(e.intersects(e.clone(), new Matrix())).toEqual(true); // A point without area can't have an intersection, thus it can't even intersect itself - expect(f.intersects(f.clone())).to.equal(false); + expect(f.intersects(f.clone())).toEqual(false); - expect(f.intersects(f.clone(), new Matrix())).to.equal(false); + expect(f.intersects(f.clone(), new Matrix())).toEqual(false); // No intersection if the transform is degenerate - expect(a.intersects(a.clone(), new Matrix().scale(0, 1))).to.equal(false); + expect(a.intersects(a.clone(), new Matrix().scale(0, 1))).toEqual(false); - expect(a.intersects(a.clone(), new Matrix().scale(0.5, 0.5))).to.equal(true); - expect(a.intersects(a.clone(), new Matrix().scale(2, 2))).to.equal(true); + expect(a.intersects(a.clone(), new Matrix().scale(0.5, 0.5))).toEqual(true); + expect(a.intersects(a.clone(), new Matrix().scale(2, 2))).toEqual(true); const m = new Matrix().translate(-50, -50).rotate(Math.PI / 4); - expect(a.intersects(a.clone(), m.clone().translate(-35, -35))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().translate(-36, -36))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().translate(135, -35))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().translate(136, -36))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().translate(-35, 135))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().translate(-36, 136))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().translate(135, 135))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().translate(136, 136))).to.equal(false); - - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-35, -35))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-36, -36))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(135, -35))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(136, -36))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-35, 135))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-36, 136))).to.equal(false); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(135, 135))).to.equal(true); - expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(136, 136))).to.equal(false); + expect(a.intersects(a.clone(), m.clone().translate(-35, -35))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().translate(-36, -36))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().translate(135, -35))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().translate(136, -36))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().translate(-35, 135))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().translate(-36, 136))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().translate(135, 135))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().translate(136, 136))).toEqual(false); + + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-35, -35))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-36, -36))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(135, -35))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(136, -36))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-35, 135))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(-36, 136))).toEqual(false); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(135, 135))).toEqual(true); + expect(a.intersects(a.clone(), m.clone().scale(-1, +1).translate(136, 136))).toEqual(false); }); }); diff --git a/packages/math/test/RoundedRectangle.tests.ts b/packages/math/test/RoundedRectangle.tests.ts index 9774714fb20..bae1e6c4cc9 100644 --- a/packages/math/test/RoundedRectangle.tests.ts +++ b/packages/math/test/RoundedRectangle.tests.ts @@ -1,67 +1,66 @@ import { RoundedRectangle } from '@pixi/math'; -import { expect } from 'chai'; -describe('RoundedRectangle', function () +describe('RoundedRectangle', () => { - it('should create a new rounded rectangle', function () + it('should create a new rounded rectangle', () => { const rrect = new RoundedRectangle(5, 5, 1, 1); - expect(rrect.x).to.equal(5); - expect(rrect.y).to.equal(5); - expect(rrect.width).to.equal(1); - expect(rrect.height).to.equal(1); - expect(rrect.radius).to.equal(20); + expect(rrect.x).toEqual(5); + expect(rrect.y).toEqual(5); + expect(rrect.width).toEqual(1); + expect(rrect.height).toEqual(1); + expect(rrect.radius).toEqual(20); }); - it('should clone a new rounded rectangle', function () + it('should clone a new rounded rectangle', () => { const rrect1 = new RoundedRectangle(0, 0, 100, 100, 40); - expect(rrect1.x).to.equal(0); - expect(rrect1.y).to.equal(0); - expect(rrect1.width).to.equal(100); - expect(rrect1.height).to.equal(100); - expect(rrect1.radius).to.equal(40); + expect(rrect1.x).toEqual(0); + expect(rrect1.y).toEqual(0); + expect(rrect1.width).toEqual(100); + expect(rrect1.height).toEqual(100); + expect(rrect1.radius).toEqual(40); const rrect2 = rrect1.clone(); - expect(rrect2.x).to.equal(0); - expect(rrect2.y).to.equal(0); - expect(rrect2.width).to.equal(100); - expect(rrect2.height).to.equal(100); - expect(rrect2.radius).to.equal(40); - expect(rrect1).to.not.equal(rrect2); + expect(rrect2.x).toEqual(0); + expect(rrect2.y).toEqual(0); + expect(rrect2.width).toEqual(100); + expect(rrect2.height).toEqual(100); + expect(rrect2.radius).toEqual(40); + expect(rrect1).not.toBe(rrect2); }); - it('should check if point is within rounded rectangle', function () + it('should check if point is within rounded rectangle', () => { const rrect1 = new RoundedRectangle(0, 0, 200, 200, 50); - expect(rrect1.contains(50, 50)).to.be.true; - expect(rrect1.contains(5, 100)).to.be.true; - expect(rrect1.contains(100, 5)).to.be.true; - expect(rrect1.contains(195, 100)).to.be.true; - expect(rrect1.contains(100, 195)).to.be.true; - expect(rrect1.contains(20, 20)).to.be.true; - expect(rrect1.contains(180, 20)).to.be.true; - expect(rrect1.contains(180, 180)).to.be.true; - expect(rrect1.contains(20, 180)).to.be.true; - expect(rrect1.contains(10, 10)).to.be.false; - expect(rrect1.contains(190, 10)).to.be.false; - expect(rrect1.contains(190, 190)).to.be.false; - expect(rrect1.contains(10, 190)).to.be.false; + expect(rrect1.contains(50, 50)).toBe(true); + expect(rrect1.contains(5, 100)).toBe(true); + expect(rrect1.contains(100, 5)).toBe(true); + expect(rrect1.contains(195, 100)).toBe(true); + expect(rrect1.contains(100, 195)).toBe(true); + expect(rrect1.contains(20, 20)).toBe(true); + expect(rrect1.contains(180, 20)).toBe(true); + expect(rrect1.contains(180, 180)).toBe(true); + expect(rrect1.contains(20, 180)).toBe(true); + expect(rrect1.contains(10, 10)).toBe(false); + expect(rrect1.contains(190, 10)).toBe(false); + expect(rrect1.contains(190, 190)).toBe(false); + expect(rrect1.contains(10, 190)).toBe(false); const rrect2 = new RoundedRectangle(0, 0, 10, 0, 1); - expect(rrect2.contains(0, 0)).to.be.false; + expect(rrect2.contains(0, 0)).toBe(false); const rrect3 = new RoundedRectangle(0, 0, 0, 10, 1); - expect(rrect3.contains(0, 0)).to.be.false; + expect(rrect3.contains(0, 0)).toBe(false); const rrect4 = new RoundedRectangle(0, 0, 10, 10, 1000); - expect(rrect4.contains(5, 5)).to.be.true; + expect(rrect4.contains(5, 5)).toBe(true); }); }); diff --git a/packages/math/test/Transform.tests.ts b/packages/math/test/Transform.tests.ts index 47c18da5cc2..b7200502785 100644 --- a/packages/math/test/Transform.tests.ts +++ b/packages/math/test/Transform.tests.ts @@ -1,11 +1,10 @@ import { Transform } from '@pixi/math'; -import { expect } from 'chai'; -describe('Transform', function () +describe('Transform', () => { - describe('setFromMatrix', function () + describe('setFromMatrix', () => { - it('should decompose negative scale into rotation', function () + it('should decompose negative scale into rotation', () => { const eps = 1e-3; @@ -24,16 +23,16 @@ describe('Transform', function () const scale = otherTransform.scale; const skew = otherTransform.skew; - expect(position.x).to.be.closeTo(20, eps); - expect(position.y).to.be.closeTo(10, eps); - expect(scale.x).to.be.closeTo(2, eps); - expect(scale.y).to.be.closeTo(3, eps); - expect(skew.x).to.equal(0); - expect(skew.y).to.equal(0); - expect(otherTransform.rotation).to.be.closeTo(-5 * Math.PI / 6, eps); + expect(position.x).toBeCloseTo(20, eps); + expect(position.y).toBeCloseTo(10, eps); + expect(scale.x).toBeCloseTo(2, eps); + expect(scale.y).toBeCloseTo(3, eps); + expect(skew.x).toEqual(0); + expect(skew.y).toEqual(0); + expect(otherTransform.rotation).toBeCloseTo(-5 * Math.PI / 6, eps); }); - it('should decompose mirror into skew', function () + it('should decompose mirror into skew', () => { const eps = 1e-3; @@ -52,16 +51,16 @@ describe('Transform', function () const scale = otherTransform.scale; const skew = otherTransform.skew; - expect(position.x).to.be.closeTo(20, eps); - expect(position.y).to.be.closeTo(10, eps); - expect(scale.x).to.be.closeTo(2, eps); - expect(scale.y).to.be.closeTo(3, eps); - expect(skew.x).to.be.closeTo(5 * Math.PI / 6, eps); - expect(skew.y).to.be.closeTo(Math.PI / 6, eps); - expect(otherTransform.rotation).to.equal(0); + expect(position.x).toBeCloseTo(20, eps); + expect(position.y).toBeCloseTo(10, eps); + expect(scale.x).toBeCloseTo(2, eps); + expect(scale.y).toBeCloseTo(3, eps); + expect(skew.x).toBeCloseTo(5 * Math.PI / 6, eps); + expect(skew.y).toBeCloseTo(Math.PI / 6, eps); + expect(otherTransform.rotation).toEqual(0); }); - it('should apply skew before scale, like in adobe animate and spine', function () + it('should apply skew before scale, like in adobe animate and spine', () => { // this example looks the same in CSS and in pixi, made with pixi-animate by @bigtimebuddy @@ -78,12 +77,12 @@ describe('Transform', function () const mat = transform.worldTransform; - expect(mat.a).to.be.closeTo(0.563, eps); - expect(mat.b).to.be.closeTo(0.100, eps); - expect(mat.c).to.be.closeTo(-3.142, eps); - expect(mat.d).to.be.closeTo(2.635, eps); - expect(mat.tx).to.be.closeTo(387.8, eps); - expect(mat.ty).to.be.closeTo(313.95, eps); + expect(mat.a).toBeCloseTo(0.563, eps); + expect(mat.b).toBeCloseTo(0.100, eps); + expect(mat.c).toBeCloseTo(-3.142, eps); + expect(mat.d).toBeCloseTo(2.635, eps); + expect(mat.tx).toBeCloseTo(387.8, eps); + expect(mat.ty).toBeCloseTo(313.95, eps); otherTransform.setFromMatrix(transform.worldTransform); @@ -91,13 +90,13 @@ describe('Transform', function () const scale = otherTransform.scale; const skew = otherTransform.skew; - expect(position.x).to.be.closeTo(387.8, eps); - expect(position.y).to.be.closeTo(313.95, eps); - expect(scale.x).to.be.closeTo(0.572, eps); - expect(scale.y).to.be.closeTo(4.101, eps); - expect(skew.x).to.be.closeTo(-0.873, eps); - expect(skew.y).to.be.closeTo(0.175, eps); - expect(otherTransform.rotation).to.be.equal(0); + expect(position.x).toBeCloseTo(387.8, eps); + expect(position.y).toBeCloseTo(313.95, eps); + expect(scale.x).toBeCloseTo(0.572, eps); + expect(scale.y).toBeCloseTo(4.101, eps); + expect(skew.x).toBeCloseTo(-0.873, eps); + expect(skew.y).toBeCloseTo(0.175, eps); + expect(otherTransform.rotation).toEqual(0); }); }); }); diff --git a/packages/mesh-extras/README.md b/packages/mesh-extras/README.md index 1d9b0e13f30..e46425fc72d 100644 --- a/packages/mesh-extras/README.md +++ b/packages/mesh-extras/README.md @@ -9,11 +9,8 @@ npm install @pixi/mesh-extras ## Usage ```js -import { MeshRenderer } from '@pixi/mesh'; -import { Renderer } from '@pixi/core'; +import '@pixi/mesh'; import { Rope } from '@pixi/mesh-extras'; -Renderer.registerPlugin('mesh', MeshRenderer); - const rope = new Rope(); ``` \ No newline at end of file diff --git a/packages/mesh-extras/package.json b/packages/mesh-extras/package.json index e04a5de9932..d9c3e458ffc 100644 --- a/packages/mesh-extras/package.json +++ b/packages/mesh-extras/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/mesh-extras", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/mesh-extras.js", - "module": "dist/esm/mesh-extras.js", - "bundle": "dist/browser/mesh-extras.js", + "module": "dist/esm/mesh-extras.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/mesh-extras.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/mesh-extras.js" + } + } + }, "description": "Custom Mesh display objects, like Rope and SimplePlane", "author": "Mat Groves", "contributors": [ @@ -20,15 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/mesh" + ] } diff --git a/packages/mesh-extras/src/NineSlicePlane.ts b/packages/mesh-extras/src/NineSlicePlane.ts index b637e4c2ddc..c0ed9862383 100644 --- a/packages/mesh-extras/src/NineSlicePlane.ts +++ b/packages/mesh-extras/src/NineSlicePlane.ts @@ -26,14 +26,12 @@ export interface NineSlicePlane extends GlobalMixins.NineSlicePlane {} * +---+----------------------+---+ * D | 7 | 8 | 9 | * +---+----------------------+---+ - * When changing this objects width and/or height: * areas 1 3 7 and 9 will remain unscaled. * areas 2 and 8 will be stretched horizontally * areas 4 and 6 will be stretched vertically * area 5 will be stretched both horizontally and vertically * - * * @memberof PIXI */ export class NineSlicePlane extends SimplePlane @@ -43,28 +41,24 @@ export class NineSlicePlane extends SimplePlane /** * The width of the left column (a). - * * @private */ _leftWidth: number; /** * The width of the right column (b) - * * @private */ _rightWidth: number; /** * The height of the top row (c) - * * @private */ _topHeight: number; /** * The height of the bottom row (d) - * * @private */ _bottomHeight: number; @@ -146,8 +140,7 @@ export class NineSlicePlane extends SimplePlane /** * Returns the smaller of a set of vertical and horizontal scale of nine slice corners. - * - * @return Smaller number of vertical and horizontal scale. + * @returns Smaller number of vertical and horizontal scale. */ private _getMinScale(): number { diff --git a/packages/mesh-extras/src/SimpleMesh.ts b/packages/mesh-extras/src/SimpleMesh.ts index 29e8512f598..33cb4269614 100644 --- a/packages/mesh-extras/src/SimpleMesh.ts +++ b/packages/mesh-extras/src/SimpleMesh.ts @@ -1,13 +1,11 @@ import { Mesh, MeshGeometry, MeshMaterial } from '@pixi/mesh'; import { Texture } from '@pixi/core'; -import type { ITypedArray, IArrayBuffer, Renderer } from '@pixi/core'; -import type { DRAW_MODES } from '@pixi/constants'; +import type { DRAW_MODES, ITypedArray, IArrayBuffer, Renderer } from '@pixi/core'; /** * The Simple Mesh class mimics Mesh in PixiJS v4, providing easy-to-use constructor arguments. * For more robust customization, use {@link PIXI.Mesh}. - * * @memberof PIXI */ export class SimpleMesh extends Mesh diff --git a/packages/mesh-extras/src/SimplePlane.ts b/packages/mesh-extras/src/SimplePlane.ts index 0b9c52cdacf..9dd32e43afe 100644 --- a/packages/mesh-extras/src/SimplePlane.ts +++ b/packages/mesh-extras/src/SimplePlane.ts @@ -14,7 +14,6 @@ import type { IDestroyOptions } from '@pixi/display'; * }; * let SimplePlane = new PIXI.SimplePlane(PIXI.Texture.from("snake.png"), points); * ``` - * * @memberof PIXI */ export class SimplePlane extends Mesh @@ -29,7 +28,7 @@ export class SimplePlane extends Mesh * @param verticesX - The number of vertices in the x-axis * @param verticesY - The number of vertices in the y-axis */ - constructor(texture: Texture, verticesX: number, verticesY: number) + constructor(texture: Texture, verticesX?: number, verticesY?: number) { const planeGeometry = new PlaneGeometry(texture.width, texture.height, verticesX, verticesY); const meshMaterial = new MeshMaterial(Texture.WHITE); @@ -99,7 +98,7 @@ export class SimplePlane extends Mesh super._render(renderer); } - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { this.shader.texture.off('update', this.textureUpdated, this); super.destroy(options); diff --git a/packages/mesh-extras/src/SimpleRope.ts b/packages/mesh-extras/src/SimpleRope.ts index 0d94dbfdb09..87074d0e3e7 100644 --- a/packages/mesh-extras/src/SimpleRope.ts +++ b/packages/mesh-extras/src/SimpleRope.ts @@ -1,9 +1,8 @@ import { Mesh, MeshMaterial } from '@pixi/mesh'; -import { WRAP_MODES } from '@pixi/constants'; +import { WRAP_MODES } from '@pixi/core'; import { RopeGeometry } from './geometry/RopeGeometry'; -import type { Texture, Renderer } from '@pixi/core'; -import type { IPoint } from '@pixi/math'; +import type { IPoint, Texture, Renderer } from '@pixi/core'; /** * The rope allows you to draw a texture across several points and then manipulate these points @@ -14,7 +13,6 @@ import type { IPoint } from '@pixi/math'; * }; * let rope = new PIXI.SimpleRope(PIXI.Texture.from("snake.png"), points); * ``` - * * @memberof PIXI */ export class SimpleRope extends Mesh @@ -42,7 +40,6 @@ export class SimpleRope extends Mesh /** * re-calculate vertices by rope points each frame - * * @member {boolean} */ this.autoUpdate = true; diff --git a/packages/mesh-extras/src/geometry/RopeGeometry.ts b/packages/mesh-extras/src/geometry/RopeGeometry.ts index 72b10d83b3f..0d641f20b7c 100644 --- a/packages/mesh-extras/src/geometry/RopeGeometry.ts +++ b/packages/mesh-extras/src/geometry/RopeGeometry.ts @@ -1,5 +1,5 @@ import { MeshGeometry } from '@pixi/mesh'; -import type { IPoint } from '@pixi/math'; +import type { IPoint } from '@pixi/core'; /** * RopeGeometry allows you to draw a geometry across several points and then manipulate these points. @@ -10,7 +10,6 @@ import type { IPoint } from '@pixi/math'; * }; * const rope = new PIXI.RopeGeometry(100, points); * ``` - * * @memberof PIXI */ export class RopeGeometry extends MeshGeometry @@ -23,7 +22,6 @@ export class RopeGeometry extends MeshGeometry /** * The width (i.e., thickness) of the rope. - * * @readonly */ _width: number; @@ -54,8 +52,7 @@ export class RopeGeometry extends MeshGeometry /** * The width (i.e., thickness) of the rope. - * - * @readOnly + * @readonly */ get width(): number { @@ -150,9 +147,7 @@ export class RopeGeometry extends MeshGeometry this.updateVertices(); } - /** - * refreshes vertices of Rope mesh - */ + /** refreshes vertices of Rope mesh */ public updateVertices(): void { const points = this.points; diff --git a/packages/mesh-extras/test/NineSlicePlane.tests.ts b/packages/mesh-extras/test/NineSlicePlane.tests.ts index e6d1e8a5264..3f3c279755a 100644 --- a/packages/mesh-extras/test/NineSlicePlane.tests.ts +++ b/packages/mesh-extras/test/NineSlicePlane.tests.ts @@ -1,40 +1,38 @@ import { NineSlicePlane } from '@pixi/mesh-extras'; -import { skipHello } from '@pixi/utils'; -import { Texture } from '@pixi/core'; -import { expect } from 'chai'; +import { Texture, utils } from '@pixi/core'; -skipHello(); +utils.skipHello(); -describe('NineSlicePlane', function () +describe('NineSlicePlane', () => { - it('should be able to create an instance', function () + it('should be able to create an instance', () => { const plane = new NineSlicePlane(Texture.WHITE); - expect(plane).to.be.an.instanceOf(NineSlicePlane); - expect(plane.leftWidth).equals(10); - expect(plane.rightWidth).equals(10); - expect(plane.topHeight).equals(10); - expect(plane.bottomHeight).equals(10); - expect(plane.width).equals(Texture.WHITE.width); - expect(plane.height).equals(Texture.WHITE.height); + expect(plane).toBeInstanceOf(NineSlicePlane); + expect(plane.leftWidth).toEqual(10); + expect(plane.rightWidth).toEqual(10); + expect(plane.topHeight).toEqual(10); + expect(plane.bottomHeight).toEqual(10); + expect(plane.width).toEqual(Texture.WHITE.width); + expect(plane.height).toEqual(Texture.WHITE.height); plane.destroy(); }); - it('shold return correct scaling for NineSlicePlane corners', function () + it('shold return correct scaling for NineSlicePlane corners', () => { const plane = new NineSlicePlane(Texture.EMPTY, 10, 10, 10, 10); plane.width = 100; plane.height = 100; - expect(plane._getMinScale()).to.equal(1); + expect(plane['_getMinScale']()).toEqual(1); plane.width = 10; plane.height = 100; - expect(plane._getMinScale()).to.equal(0.5); + expect(plane['_getMinScale']()).toEqual(0.5); plane.width = 100; plane.height = 10; - expect(plane._getMinScale()).to.equal(0.5); + expect(plane['_getMinScale']()).toEqual(0.5); plane.destroy(); }); diff --git a/packages/mesh-extras/test/SimpleMesh.tests.ts b/packages/mesh-extras/test/SimpleMesh.tests.ts index 509aeadbc54..29b31b39172 100644 --- a/packages/mesh-extras/test/SimpleMesh.tests.ts +++ b/packages/mesh-extras/test/SimpleMesh.tests.ts @@ -1,26 +1,22 @@ import { SimpleMesh } from '@pixi/mesh-extras'; -import { skipHello } from '@pixi/utils'; -import { Renderer, BatchRenderer } from '@pixi/core'; -import { expect } from 'chai'; +import { Renderer, utils } from '@pixi/core'; -skipHello(); +utils.skipHello(); -describe('SimpleMesh', function () +describe('SimpleMesh', () => { - it('should create a simple mesh with defaults', function () + it('should create a simple mesh with defaults', () => { const mesh = new SimpleMesh(); - expect(mesh).to.be.instanceOf(SimpleMesh); - expect(mesh.autoUpdate).to.be.true; + expect(mesh).toBeInstanceOf(SimpleMesh); + expect(mesh.autoUpdate).toBe(true); mesh.destroy(); }); - it('should render the rope', function () + it('should render the rope', () => { - Renderer.registerPlugin('batch', BatchRenderer); - const renderer = new Renderer(); const mesh = new SimpleMesh(); diff --git a/packages/mesh-extras/test/SimplePlane.tests.ts b/packages/mesh-extras/test/SimplePlane.tests.ts index 926d680a004..906aac0c4e7 100644 --- a/packages/mesh-extras/test/SimplePlane.tests.ts +++ b/packages/mesh-extras/test/SimplePlane.tests.ts @@ -1,63 +1,72 @@ import { SimplePlane } from '@pixi/mesh-extras'; -import { skipHello } from '@pixi/utils'; -import { Loader } from '@pixi/loaders'; -import { Point } from '@pixi/math'; -import { Renderer, BatchRenderer, RenderTexture, Texture } from '@pixi/core'; -import { expect } from 'chai'; +import { Point, Renderer, RenderTexture, Texture, utils } from '@pixi/core'; +import { Cache, loadTextures } from '@pixi/assets'; +import { Loader } from '../../assets/src/loader/Loader'; -skipHello(); +import type { PlaneGeometry } from '@pixi/mesh-extras'; -// TODO: fix with webglrenderer -describe('SimplePlane', function () +utils.skipHello(); + +describe('SimplePlane', () => { - it('should create a plane from an external image', function (done) + let loader: Loader; + const serverPath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/mesh-extras/test/resources/` + : 'http://localhost:8080/mesh-extras/test/resources/'; + + beforeEach(() => { - const loader = new Loader(); + Cache.reset(); + loader.reset(); + }); - loader.add('testBitmap', `file://${__dirname}/resources/bitmap-1.png`) - .load(function (loader, resources) - { - const plane = new SimplePlane(resources.testBitmap.texture, 100, 100); + beforeAll(() => + { + loader = new Loader(); + loader['_parsers'].push(loadTextures); + }); - expect(plane.geometry.segWidth).to.equal(100); - expect(plane.geometry.segHeight).to.equal(100); - done(); - }); + it('should create a plane from an external image', async () => + { + const texture = await loader.load(`${serverPath}bitmap-1.png`); + + const plane = new SimplePlane(texture, 100, 100); + + expect((plane.geometry as PlaneGeometry).segWidth).toEqual(100); + expect((plane.geometry as PlaneGeometry).segHeight).toEqual(100); }); - it('should create a new empty textured SimplePlane', function () + it('should create a new empty textured SimplePlane', () => { const plane = new SimplePlane(Texture.EMPTY, 100, 100); - expect(plane.geometry.segWidth).to.equal(100); - expect(plane.geometry.segHeight).to.equal(100); + expect((plane.geometry as PlaneGeometry).segWidth).toEqual(100); + expect((plane.geometry as PlaneGeometry).segHeight).toEqual(100); }); - describe('containsPoint', function () + describe('containsPoint', () => { - it('should return true when point inside', function () + it('should return true when point inside', () => { const point = new Point(10, 10); const texture = RenderTexture.create({ width: 20, height: 30 }); const plane = new SimplePlane(texture, 100, 100); - expect(plane.containsPoint(point)).to.be.true; + expect(plane.containsPoint(point)).toBe(true); }); - it('should return false when point outside', function () + it('should return false when point outside', () => { const point = new Point(100, 100); const texture = RenderTexture.create({ width: 20, height: 30 }); const plane = new SimplePlane(texture, 100, 100); - expect(plane.containsPoint(point)).to.be.false; + expect(plane.containsPoint(point)).toBe(false); }); }); - it('should render the plane', function () + it('should render the plane', () => { - Renderer.registerPlugin('batch', BatchRenderer); - const renderer = new Renderer(); const plane = new SimplePlane(Texture.WHITE, 100, 100); diff --git a/packages/mesh-extras/test/SimpleRope.tests.ts b/packages/mesh-extras/test/SimpleRope.tests.ts index 6ffe55b2b82..0fe7ef075f7 100644 --- a/packages/mesh-extras/test/SimpleRope.tests.ts +++ b/packages/mesh-extras/test/SimpleRope.tests.ts @@ -1,39 +1,42 @@ +import { Cache, loadTextures } from '@pixi/assets'; +import { Renderer, Texture, Point, utils } from '@pixi/core'; import { SimpleRope } from '@pixi/mesh-extras'; -import { skipHello } from '@pixi/utils'; -import { Loader } from '@pixi/loaders'; -import { Point } from '@pixi/math'; -import { Renderer, Texture, BatchRenderer } from '@pixi/core'; -import { expect } from 'chai'; +import { Loader } from '../../assets/src/loader/Loader'; -skipHello(); +utils.skipHello(); -describe('SimpleRope', function () +describe('SimpleRope', () => { - it('should create a rope from an external image', function (done: () => void) - { - const loader = new Loader(); - - loader.add('testBitmap', `file://${__dirname}/resources/bitmap-1.png`) - .load(function (loader, resources) - { - const rope = new SimpleRope(resources.testBitmap.texture, [new Point(0, 0), new Point(0, 1)]); + let loader: Loader; + const serverPath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/mesh-extras/test/resources/` + : 'http://localhost:8080/mesh-extras/test/resources/'; - expect(rope).to.be.instanceof(SimpleRope); - expect(rope.autoUpdate).to.be.true; + beforeEach(() => + { + Cache.reset(); + loader.reset(); + }); - rope.destroy(); - resources.testBitmap.texture.destroy(true); + beforeAll(() => + { + loader = new Loader(); + loader['_parsers'].push(loadTextures); + }); + it('should create a rope from an external image', async () => + { + const texture = await loader.load(`${serverPath}bitmap-1.png`); + const rope = new SimpleRope(texture, [new Point(0, 0), new Point(0, 1)]); - loader.reset(); + expect(rope).toBeInstanceOf(SimpleRope); + expect(rope.autoUpdate).toBe(true); - done(); - }); + rope.destroy(); + texture.destroy(true); }); - it('should render the rope', function () + it('should render the rope', () => { - Renderer.registerPlugin('batch', BatchRenderer); - const renderer = new Renderer(); const rope = new SimpleRope(Texture.WHITE, [new Point(0, 0), new Point(0, 1)]); diff --git a/packages/mesh/README.md b/packages/mesh/README.md index e59cb1e1249..6f7daeab3f5 100644 --- a/packages/mesh/README.md +++ b/packages/mesh/README.md @@ -9,8 +9,5 @@ npm install @pixi/mesh ## Usage ```js -import { MeshRenderer } from '@pixi/mesh'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('mesh', MeshRenderer); +import '@pixi/mesh'; ``` \ No newline at end of file diff --git a/packages/mesh/package.json b/packages/mesh/package.json index c214d097c06..e4539909b8e 100644 --- a/packages/mesh/package.json +++ b/packages/mesh/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/mesh", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/mesh.js", - "module": "dist/esm/mesh.js", - "bundle": "dist/browser/mesh.js", + "module": "dist/esm/mesh.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/mesh.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/mesh.js" + } + } + }, "description": "Core Mesh functionality", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/mesh/src/Mesh.ts b/packages/mesh/src/Mesh.ts index a1002e703a5..9989b65882d 100644 --- a/packages/mesh/src/Mesh.ts +++ b/packages/mesh/src/Mesh.ts @@ -1,14 +1,10 @@ -import { Shader, State } from '@pixi/core'; -import { Point, Polygon } from '@pixi/math'; -import { BLEND_MODES, DRAW_MODES } from '@pixi/constants'; +import { State, DRAW_MODES, settings, Point, Polygon } from '@pixi/core'; import { Container } from '@pixi/display'; -import { settings } from '@pixi/settings'; import { MeshBatchUvs } from './MeshBatchUvs'; -import { MeshMaterial } from './MeshMaterial'; +import type { MeshMaterial } from './MeshMaterial'; import type { IDestroyOptions } from '@pixi/display'; -import type { Texture, Renderer, Geometry, Buffer } from '@pixi/core'; -import type { IPointData } from '@pixi/math'; +import type { BLEND_MODES, IPointData, Texture, Renderer, Geometry, Buffer, Shader } from '@pixi/core'; const tempPoint = new Point(); const tempPolygon = new Polygon(); @@ -29,7 +25,6 @@ export interface Mesh extends GlobalMixins.Mesh {} * - State - This is the state of WebGL required to render the mesh. * * Through a combination of the above elements you can render anything you want, 2D or 3D! - * * @memberof PIXI */ export class Mesh extends Container @@ -37,7 +32,6 @@ export class Mesh extends Container /** * Represents the vertex and fragment shaders that processes the geometry and runs on the GPU. * Can be shared between multiple Mesh objects. - * * @type {PIXI.Shader|PIXI.MeshMaterial} */ public shader: T; @@ -53,14 +47,12 @@ export class Mesh extends Container /** * Typically the index of the IndexBuffer where to start drawing. - * * @default 0 */ public start: number; /** * How much of the geometry to draw, by default `0` renders everything. - * * @default 0 */ public size: number; @@ -70,10 +62,7 @@ export class Mesh extends Container /** This is the caching layer used by the batcher. */ private vertexData: Float32Array; - /** - * If geometry is changed used to decide to re-transform - * the vertexData. - */ + /** If geometry is changed used to decide to re-transform the vertexData. */ private vertexDirty: number; private _transformID: number; @@ -86,14 +75,12 @@ export class Mesh extends Container // Internal-only properties /** * These are used as easy access for batching. - * * @private */ uvs: Float32Array; /** * These are used as easy access for batching. - * * @private */ indices: Uint16Array; @@ -167,7 +154,6 @@ export class Mesh extends Container /** * To change mesh uv's, change its uvBuffer data and increment its _updateID. - * * @readonly */ get uvBuffer(): Buffer @@ -178,7 +164,6 @@ export class Mesh extends Container /** * To change mesh vertices, change its uvBuffer data and increment its _updateID. * Incrementing _updateID is optional because most of Mesh objects do it anyway. - * * @readonly */ get verticesBuffer(): Buffer @@ -200,7 +185,6 @@ export class Mesh extends Container /** * The blend mode to be applied to the Mesh. Apply a value of * `PIXI.BLEND_MODES.NORMAL` to reset the blend mode. - * * @default PIXI.BLEND_MODES.NORMAL; */ set blendMode(value: BLEND_MODES) @@ -218,7 +202,6 @@ export class Mesh extends Container * Advantages can include sharper image quality (like text) and faster rendering on canvas. * The main disadvantage is movement of objects may appear less smooth. * To set the global default, change {@link PIXI.settings.ROUND_PIXELS} - * * @default false */ set roundPixels(value: boolean) @@ -240,7 +223,6 @@ export class Mesh extends Container * `0xFFFFFF` will remove any tint effect. * * Null for non-MeshMaterial shaders - * * @default 0xFFFFFF */ get tint(): number @@ -253,11 +235,7 @@ export class Mesh extends Container (this.shader as unknown as MeshMaterial).tint = value; } - /** - * The texture that the Mesh uses. - * - * Null for non-MeshMaterial shaders - */ + /** The texture that the Mesh uses. Null for non-MeshMaterial shaders */ get texture(): Texture { return 'texture' in this.shader ? (this.shader as unknown as MeshMaterial).texture : null; @@ -270,7 +248,6 @@ export class Mesh extends Container /** * Standard renderer draw. - * * @param renderer - Instance to renderer. */ protected _render(renderer: Renderer): void @@ -297,7 +274,6 @@ export class Mesh extends Container /** * Standard non-batching way of rendering. - * * @param renderer - Instance to renderer. */ protected _renderDefault(renderer: Renderer): void @@ -328,7 +304,6 @@ export class Mesh extends Container /** * Rendering by using the Batch system. - * * @param renderer - Instance to renderer. */ protected _renderToBatch(renderer: Renderer): void @@ -440,9 +415,8 @@ export class Mesh extends Container /** * Tests if a point is inside this mesh. Works only for PIXI.DRAW_MODES.TRIANGLES. - * * @param point - The point to test. - * @return - The result of the test. + * @returns - The result of the test. */ public containsPoint(point: IPointData): boolean { @@ -482,7 +456,7 @@ export class Mesh extends Container return false; } - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { super.destroy(options); @@ -500,9 +474,6 @@ export class Mesh extends Container this.vertexData = null; } - /** - * The maximum number of vertices to consider batchable. Generally, the complexity - * of the geometry. - */ + /** The maximum number of vertices to consider batchable. Generally, the complexity of the geometry. */ public static BATCHABLE_SIZE = 100; } diff --git a/packages/mesh/src/MeshBatchUvs.ts b/packages/mesh/src/MeshBatchUvs.ts index 3fbc0fc53c6..5c1b6ba08ca 100644 --- a/packages/mesh/src/MeshBatchUvs.ts +++ b/packages/mesh/src/MeshBatchUvs.ts @@ -2,7 +2,6 @@ import type { TextureMatrix, Buffer } from '@pixi/core'; /** * Class controls cache for UV mapping from Texture normal space to BaseTexture normal space. - * * @memberof PIXI */ export class MeshBatchUvs @@ -39,7 +38,6 @@ export class MeshBatchUvs /** * Updates - * * @param forceUpdate - force the update */ public update(forceUpdate?: boolean): void diff --git a/packages/mesh/src/MeshGeometry.ts b/packages/mesh/src/MeshGeometry.ts index adf48f5be9b..254101177ee 100644 --- a/packages/mesh/src/MeshGeometry.ts +++ b/packages/mesh/src/MeshGeometry.ts @@ -1,5 +1,4 @@ -import { TYPES } from '@pixi/constants'; -import { Buffer, Geometry } from '@pixi/core'; +import { Buffer, Geometry, TYPES } from '@pixi/core'; import type { IArrayBuffer } from '@pixi/core'; @@ -16,7 +15,6 @@ import type { IArrayBuffer } from '@pixi/core'; * geometry.addIndex([0,1,2,1,3,2]); * * ``` - * * @memberof PIXI */ export class MeshGeometry extends Geometry @@ -26,7 +24,6 @@ export class MeshGeometry extends Geometry * Dirty flag to limit update calls on Mesh. For example, * limiting updates on a single Mesh instance with a shared Geometry * within the render loop. - * * @private * @default -1 */ @@ -54,7 +51,6 @@ export class MeshGeometry extends Geometry /** * If the vertex position is updated. - * * @readonly * @private */ diff --git a/packages/mesh/src/MeshMaterial.ts b/packages/mesh/src/MeshMaterial.ts index fec1367d443..bf65f68e384 100644 --- a/packages/mesh/src/MeshMaterial.ts +++ b/packages/mesh/src/MeshMaterial.ts @@ -1,18 +1,16 @@ -import { Program, Shader, TextureMatrix } from '@pixi/core'; -import { Matrix } from '@pixi/math'; -import { premultiplyTintToRgba } from '@pixi/utils'; +import { Matrix, utils, Program, Shader, TextureMatrix } from '@pixi/core'; import fragment from './shader/mesh.frag'; import vertex from './shader/mesh.vert'; import type { Texture } from '@pixi/core'; -import type { Dict } from '@pixi/utils'; -export interface IMeshMaterialOptions { +export interface IMeshMaterialOptions +{ alpha?: number; tint?: number; pluginName?: string; program?: Program; - uniforms?: Dict; + uniforms?: utils.Dict; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -20,28 +18,24 @@ export interface MeshMaterial extends GlobalMixins.MeshMaterial {} /** * Slightly opinionated default shader for PixiJS 2D objects. - * * @memberof PIXI */ export class MeshMaterial extends Shader { /** * TextureMatrix instance for this Mesh, used to track Texture changes. - * * @readonly */ public readonly uvMatrix: TextureMatrix; /** * `true` if shader can be batch with the renderer's batch system. - * * @default true */ public batchable: boolean; /** * Renderer plugin for batching. - * * @default 'batch' */ public pluginName: string; @@ -51,7 +45,6 @@ export class MeshMaterial extends Shader /** * Only do update if tint or alpha changes. - * * @private * @default false */ @@ -110,6 +103,11 @@ export class MeshMaterial extends Shader { if (this.uniforms.uSampler !== value) { + if (!this.uniforms.uSampler.baseTexture.alphaMode !== !value.baseTexture.alphaMode) + { + this._colorDirty = true; + } + this.uniforms.uSampler = value; this.uvMatrix.texture = value; } @@ -117,7 +115,6 @@ export class MeshMaterial extends Shader /** * This gets automatically set by the object using this. - * * @default 1 */ set alpha(value: number) @@ -134,7 +131,6 @@ export class MeshMaterial extends Shader /** * Multiply tint for the material. - * * @default 0xFFFFFF */ set tint(value: number) @@ -150,10 +146,7 @@ export class MeshMaterial extends Shader return this._tint; } - /** - * Gets called automatically by the Mesh. Intended to be overridden for custom - * {@link MeshMaterial} objects. - */ + /** Gets called automatically by the Mesh. Intended to be overridden for custom {@link MeshMaterial} objects. */ public update(): void { if (this._colorDirty) @@ -161,7 +154,7 @@ export class MeshMaterial extends Shader this._colorDirty = false; const baseTexture = this.texture.baseTexture; - premultiplyTintToRgba( + utils.premultiplyTintToRgba( this._tint, this._alpha, this.uniforms.uColor, (baseTexture.alphaMode as unknown as boolean) ); } diff --git a/packages/mesh/test/Mesh.tests.ts b/packages/mesh/test/Mesh.tests.ts index 94623eea402..777706547d1 100644 --- a/packages/mesh/test/Mesh.tests.ts +++ b/packages/mesh/test/Mesh.tests.ts @@ -1,73 +1,71 @@ import { Mesh, MeshGeometry, MeshMaterial } from '@pixi/mesh'; -import { skipHello } from '@pixi/utils'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { Texture, utils } from '@pixi/core'; -skipHello(); +utils.skipHello(); -describe('Mesh', function () +describe('Mesh', () => { - it('should dispose geometry correctly', function () + it('should dispose geometry correctly', () => { - const geometry1 = new MeshGeometry([0, 0]); - const geometry2 = new MeshGeometry([1, 1]); + const geometry1 = new MeshGeometry(new Float32Array([0, 0])); + const geometry2 = new MeshGeometry(new Float32Array([1, 1])); - const dispose1 = sinon.spy(geometry1, 'dispose'); - const dispose2 = sinon.spy(geometry2, 'dispose'); + const dispose1 = jest.spyOn(geometry1, 'dispose'); + const dispose2 = jest.spyOn(geometry2, 'dispose'); - expect(geometry1.refCount).to.equal(0); - expect(geometry2.refCount).to.equal(0); - expect(dispose1.called).to.be.false; - expect(dispose2.called).to.be.false; + expect(geometry1.refCount).toEqual(0); + expect(geometry2.refCount).toEqual(0); + expect(dispose1).not.toHaveBeenCalled(); + expect(dispose2).not.toHaveBeenCalled(); - const mesh = new Mesh(geometry1, new MeshMaterial()); + const mesh = new Mesh(geometry1, new MeshMaterial(Texture.EMPTY)); - expect(mesh.geometry).to.equal(geometry1); - expect(mesh.vertexDirty).to.equal(-1); - expect(geometry1.refCount).to.equal(1); - expect(geometry2.refCount).to.equal(0); - expect(dispose1.called).to.be.false; - expect(dispose2.called).to.be.false; + expect(mesh.geometry).toEqual(geometry1); + expect(mesh['vertexDirty']).toEqual(-1); + expect(geometry1.refCount).toEqual(1); + expect(geometry2.refCount).toEqual(0); + expect(dispose1).not.toHaveBeenCalled(); + expect(dispose2).not.toHaveBeenCalled(); mesh.calculateVertices(); - expect(mesh.vertexDirty).to.equal(mesh.verticesBuffer._updateID); - expect(mesh.vertexData[0]).to.equal(0); - expect(mesh.vertexData[1]).to.equal(0); + expect(mesh['vertexDirty']).toEqual(mesh.verticesBuffer._updateID); + expect(mesh['vertexData'][0]).toEqual(0); + expect(mesh['vertexData'][1]).toEqual(0); mesh.geometry = geometry1; - expect(mesh.geometry).to.equal(geometry1); - expect(mesh.vertexDirty).to.equal(mesh.verticesBuffer._updateID); - expect(mesh.vertexData[0]).to.equal(0); - expect(mesh.vertexData[1]).to.equal(0); - expect(geometry1.refCount).to.equal(1); - expect(geometry2.refCount).to.equal(0); - expect(dispose1.called).to.be.false; - expect(dispose2.called).to.be.false; + expect(mesh.geometry).toEqual(geometry1); + expect(mesh['vertexDirty']).toEqual(mesh.verticesBuffer._updateID); + expect(mesh['vertexData'][0]).toEqual(0); + expect(mesh['vertexData'][1]).toEqual(0); + expect(geometry1.refCount).toEqual(1); + expect(geometry2.refCount).toEqual(0); + expect(dispose1).not.toHaveBeenCalled(); + expect(dispose2).not.toHaveBeenCalled(); mesh.geometry = geometry2; - expect(mesh.geometry).to.equal(geometry2); - expect(mesh.vertexDirty).to.equal(-1); - expect(geometry1.refCount).to.equal(0); - expect(geometry2.refCount).to.equal(1); - expect(dispose1.called).to.be.true; - expect(dispose2.called).to.be.false; + expect(mesh.geometry).toEqual(geometry2); + expect(mesh['vertexDirty']).toEqual(-1); + expect(geometry1.refCount).toEqual(0); + expect(geometry2.refCount).toEqual(1); + expect(dispose1).toBeCalled(); + expect(dispose2).not.toHaveBeenCalled(); mesh.calculateVertices(); - expect(mesh.vertexDirty).to.equal(mesh.verticesBuffer._updateID); - expect(mesh.vertexData[0]).to.equal(1); - expect(mesh.vertexData[1]).to.equal(1); + expect(mesh['vertexDirty']).toEqual(mesh.verticesBuffer._updateID); + expect(mesh['vertexData'][0]).toEqual(1); + expect(mesh['vertexData'][1]).toEqual(1); mesh.destroy(); - expect(mesh.geometry).to.equal(null); - expect(mesh.vertexDirty).to.equal(-1); - expect(geometry1.refCount).to.equal(0); - expect(geometry2.refCount).to.equal(0); - expect(dispose1.called).to.be.true; - expect(dispose2.called).to.be.true; + expect(mesh.geometry).toEqual(null); + expect(mesh['vertexDirty']).toEqual(-1); + expect(geometry1.refCount).toEqual(0); + expect(geometry2.refCount).toEqual(0); + expect(dispose1).toBeCalled(); + expect(dispose2).toBeCalled(); }); }); diff --git a/packages/mixin-cache-as-bitmap/global.d.ts b/packages/mixin-cache-as-bitmap/global.d.ts index 8fadc0b8a38..cd83cbab657 100644 --- a/packages/mixin-cache-as-bitmap/global.d.ts +++ b/packages/mixin-cache-as-bitmap/global.d.ts @@ -1,6 +1,7 @@ declare namespace GlobalMixins { - interface DisplayObject { + interface DisplayObject + { cacheAsBitmap: boolean; cacheAsBitmapResolution: number; cacheAsBitmapMultisample: import('@pixi/constants').MSAA_QUALITY; @@ -12,9 +13,9 @@ declare namespace GlobalMixins _initCachedDisplayObject(renderer: import('@pixi/core').Renderer): void; _calculateCachedBounds(): void; _getCachedLocalBounds(): import('@pixi/math').Rectangle; - _renderCachedCanvas(renderer: import('@pixi/core').AbstractRenderer): void; - _initCachedDisplayObjectCanvas(renderer: import('@pixi/core').AbstractRenderer): void; + _renderCachedCanvas(renderer: import('@pixi/core').IRenderer): void; + _initCachedDisplayObjectCanvas(renderer: import('@pixi/core').IRenderer): void; _destroyCachedDisplayObject(): void; - _cacheAsBitmapDestroy(options?: import('@pixi/display').IDestroyOptions|boolean): void; + _cacheAsBitmapDestroy(options?: import('@pixi/display').IDestroyOptions | boolean): void; } } diff --git a/packages/mixin-cache-as-bitmap/package.json b/packages/mixin-cache-as-bitmap/package.json index 58db6115974..2ed68683b36 100644 --- a/packages/mixin-cache-as-bitmap/package.json +++ b/packages/mixin-cache-as-bitmap/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/mixin-cache-as-bitmap", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/mixin-cache-as-bitmap.js", - "module": "dist/esm/mixin-cache-as-bitmap.js", - "bundle": "dist/browser/mixin-cache-as-bitmap.js", - "bundleNoExports": true, + "module": "dist/esm/mixin-cache-as-bitmap.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/mixin-cache-as-bitmap.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/mixin-cache-as-bitmap.js" + } + } + }, "description": "Mixin to allow caching container and its children to a bitmap texture", "author": "Mat Groves", "contributors": [ @@ -21,16 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/sprite" + ] } diff --git a/packages/mixin-cache-as-bitmap/src/index.ts b/packages/mixin-cache-as-bitmap/src/index.ts index 98c0a54946c..dd61c25c23e 100644 --- a/packages/mixin-cache-as-bitmap/src/index.ts +++ b/packages/mixin-cache-as-bitmap/src/index.ts @@ -1,15 +1,17 @@ -import { Texture, BaseTexture, RenderTexture, Renderer, MaskData, AbstractRenderer } from '@pixi/core'; +import { Texture, BaseTexture, RenderTexture, Matrix, utils, MSAA_QUALITY, settings } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; -import { Container, DisplayObject, IDestroyOptions } from '@pixi/display'; -import { IPointData, Matrix, Rectangle } from '@pixi/math'; -import { uid } from '@pixi/utils'; -import { settings } from '@pixi/settings'; -import { MSAA_QUALITY } from '@pixi/constants'; +import { DisplayObject } from '@pixi/display'; + +import type { Renderer, MaskData, IRenderer, IPointData, Rectangle } from '@pixi/core'; +import type { Container, IDestroyOptions } from '@pixi/display'; // Don't import CanvasRender to remove dependency on this optional package // this type should satisify these requirements for cacheAsBitmap types -interface CanvasRenderer extends AbstractRenderer { - context: CanvasRenderingContext2D; +interface CanvasRenderer extends IRenderer +{ + canvasContext: { + activeContext: CanvasRenderingContext2D; + } } const _tempMatrix = new Matrix(); @@ -31,12 +33,12 @@ export class CacheData { public textureCacheId: string; public originalRender: (renderer: Renderer) => void; - public originalRenderCanvas: (renderer: AbstractRenderer) => void; + public originalRenderCanvas: (renderer: IRenderer) => void; public originalCalculateBounds: () => void; public originalGetLocalBounds: (rect?: Rectangle) => Rectangle; public originalUpdateTransform: () => void; - public originalDestroy: (options?: IDestroyOptions|boolean) => void; - public originalMask: Container|MaskData; + public originalDestroy: (options?: IDestroyOptions | boolean) => void; + public originalMask: Container | MaskData; public originalFilterArea: Rectangle; public originalContainsPoint: (point: IPointData) => boolean; public sprite: Sprite; @@ -65,7 +67,6 @@ Object.defineProperties(DisplayObject.prototype, { * but can be overriden for performance. Lower values will reduce memory usage at the expense * of render quality. A falsey value of `null` or `0` will default to the renderer's resolution. * If `cacheAsBitmap` is set to `true`, this will re-render with the new resolution. - * * @member {number} cacheAsBitmapResolution * @memberof PIXI.DisplayObject# * @default null @@ -97,7 +98,6 @@ Object.defineProperties(DisplayObject.prototype, { * The number of samples to use for cacheAsBitmap. If set to `null`, the renderer's * sample count is used. * If `cacheAsBitmap` is set to `true`, this will re-render with the new number of samples. - * * @member {number} cacheAsBitmapMultisample * @memberof PIXI.DisplayObject# * @default PIXI.MSAA_QUALITY.NONE @@ -133,7 +133,6 @@ Object.defineProperties(DisplayObject.prototype, { * * IMPORTANT GOTCHA - Make sure that all your textures are preloaded BEFORE setting this property to true * as it will take a snapshot of what is currently there. If the textures have not loaded then they will not appear. - * * @member {boolean} * @memberof PIXI.DisplayObject# */ @@ -209,7 +208,6 @@ Object.defineProperties(DisplayObject.prototype, { /** * Renders a cached version of the sprite with WebGL - * * @private * @method _renderCached * @memberof PIXI.DisplayObject# @@ -231,7 +229,6 @@ DisplayObject.prototype._renderCached = function _renderCached(renderer: Rendere /** * Prepares the WebGL renderer to cache the sprite - * * @private * @method _initCachedDisplayObject * @memberof PIXI.DisplayObject# @@ -239,7 +236,7 @@ DisplayObject.prototype._renderCached = function _renderCached(renderer: Rendere */ DisplayObject.prototype._initCachedDisplayObject = function _initCachedDisplayObject(renderer: Renderer): void { - if (this._cacheData && this._cacheData.sprite) + if (this._cacheData?.sprite) { return; } @@ -260,7 +257,7 @@ DisplayObject.prototype._initCachedDisplayObject = function _initCachedDisplayOb const bounds = (this as Container).getLocalBounds(null, true).clone(); // add some padding! - if (this.filters && this.filters.length) + if (this.filters?.length) { const padding = this.filters[0].padding; @@ -287,7 +284,7 @@ DisplayObject.prototype._initCachedDisplayObject = function _initCachedDisplayOb multisample: this.cacheAsBitmapMultisample ?? renderer.multisample, }); - const textureCacheId = `cacheAsBitmap_${uid()}`; + const textureCacheId = `cacheAsBitmap_${utils.uid()}`; this._cacheData.textureCacheId = textureCacheId; @@ -349,13 +346,12 @@ DisplayObject.prototype._initCachedDisplayObject = function _initCachedDisplayOb /** * Renders a cached version of the sprite with canvas - * * @private * @method _renderCachedCanvas * @memberof PIXI.DisplayObject# * @param {PIXI.CanvasRenderer} renderer - The canvas renderer */ -DisplayObject.prototype._renderCachedCanvas = function _renderCachedCanvas(renderer: AbstractRenderer): void +DisplayObject.prototype._renderCachedCanvas = function _renderCachedCanvas(renderer: IRenderer): void { if (!this.visible || this.worldAlpha <= 0 || !this.renderable) { @@ -371,7 +367,6 @@ DisplayObject.prototype._renderCachedCanvas = function _renderCachedCanvas(rende // TODO this can be the same as the WebGL version.. will need to do a little tweaking first though.. /** * Prepares the Canvas renderer to cache the sprite - * * @private * @method _initCachedDisplayObjectCanvas * @memberof PIXI.DisplayObject# @@ -381,7 +376,7 @@ DisplayObject.prototype._initCachedDisplayObjectCanvas = function _initCachedDis renderer: CanvasRenderer ): void { - if (this._cacheData && this._cacheData.sprite) + if (this._cacheData?.sprite) { return; } @@ -393,14 +388,14 @@ DisplayObject.prototype._initCachedDisplayObjectCanvas = function _initCachedDis this.alpha = 1; - const cachedRenderTarget = renderer.context; + const cachedRenderTarget = renderer.canvasContext.activeContext; const cachedProjectionTransform = (renderer as any)._projTransform; bounds.ceil(settings.RESOLUTION); const renderTexture = RenderTexture.create({ width: bounds.width, height: bounds.height }); - const textureCacheId = `cacheAsBitmap_${uid()}`; + const textureCacheId = `cacheAsBitmap_${utils.uid()}`; this._cacheData.textureCacheId = textureCacheId; @@ -422,7 +417,7 @@ DisplayObject.prototype._initCachedDisplayObjectCanvas = function _initCachedDis renderer.render(this, { renderTexture, clear: true, transform: m, skipUpdateTransform: false }); // now restore the state be setting the new properties - renderer.context = cachedRenderTarget; + renderer.canvasContext.activeContext = cachedRenderTarget; (renderer as any)._projTransform = cachedProjectionTransform; this.renderCanvas = this._renderCachedCanvas; @@ -465,7 +460,6 @@ DisplayObject.prototype._initCachedDisplayObjectCanvas = function _initCachedDis /** * Calculates the bounds of the cached sprite - * * @private * @method */ @@ -479,10 +473,9 @@ DisplayObject.prototype._calculateCachedBounds = function _calculateCachedBounds /** * Gets the bounds of the cached sprite. - * * @private * @method - * @return {Rectangle} The local bounds. + * @returns {Rectangle} The local bounds. */ DisplayObject.prototype._getCachedLocalBounds = function _getCachedLocalBounds(): Rectangle { @@ -491,7 +484,6 @@ DisplayObject.prototype._getCachedLocalBounds = function _getCachedLocalBounds() /** * Destroys the cached sprite. - * * @private * @method */ @@ -508,14 +500,13 @@ DisplayObject.prototype._destroyCachedDisplayObject = function _destroyCachedDis /** * Destroys the cached object. - * * @private * @method * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options * have been set to that value. * Used when destroying containers, see the Container.destroy method. */ -DisplayObject.prototype._cacheAsBitmapDestroy = function _cacheAsBitmapDestroy(options?: IDestroyOptions|boolean): void +DisplayObject.prototype._cacheAsBitmapDestroy = function _cacheAsBitmapDestroy(options?: IDestroyOptions | boolean): void { this.cacheAsBitmap = false; this.destroy(options); diff --git a/packages/mixin-cache-as-bitmap/test/cacheAsBitmap.tests.ts b/packages/mixin-cache-as-bitmap/test/cacheAsBitmap.tests.ts index 1f059c7d072..98cc0a90fa1 100644 --- a/packages/mixin-cache-as-bitmap/test/cacheAsBitmap.tests.ts +++ b/packages/mixin-cache-as-bitmap/test/cacheAsBitmap.tests.ts @@ -1,29 +1,29 @@ import { DisplayObject, Container } from '@pixi/display'; -import { Renderer, Filter } from '@pixi/core'; -import { Rectangle } from '@pixi/math'; -import { expect } from 'chai'; +import { Rectangle, Renderer, Filter } from '@pixi/core'; import '@pixi/mixin-cache-as-bitmap'; -describe('DisplayObject#cacheAsBitmap', function () +describe('DisplayObject#cacheAsBitmap', () => { - it('should contain property', function () + it('should contain property', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); - expect(obj.cacheAsBitmap).to.be.not.undefined; - expect(obj.cacheAsBitmap).to.be.a('boolean'); - expect(obj.cacheAsBitmap).to.be.false; + expect(obj.cacheAsBitmap).toBeDefined(); + expect(obj.cacheAsBitmap).toBeBoolean(); + expect(obj.cacheAsBitmap).toBe(false); }); - it('should enable cacheAsBitmap', function () + it('should enable cacheAsBitmap', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); obj.cacheAsBitmap = true; }); - it('should respect filters', function () + it('should respect filters', () => { const par = new Container(); const obj = new Container(); @@ -35,7 +35,8 @@ describe('DisplayObject#cacheAsBitmap', function () obj.position.set(5, 15); obj.updateTransform(); obj.cacheAsBitmap = true; - obj._calculateBounds = function () + // eslint-disable-next-line func-names + obj['_calculateBounds'] = function () { this._bounds.clear(); this._bounds.addFrame(this.transform, 0, 0, 10, 11); @@ -52,18 +53,18 @@ describe('DisplayObject#cacheAsBitmap', function () let src = renderer.renderTexture.sourceFrame; let dest = renderer.renderTexture.destinationFrame; - expect(src.toString()).to.equal(srcExpected.toString()); - expect(dest.toString()).to.equal(destExpected.toString()); + expect(src.toString()).toEqual(srcExpected.toString()); + expect(dest.toString()).toEqual(destExpected.toString()); obj.render(renderer); src = renderer.renderTexture.sourceFrame; dest = renderer.renderTexture.destinationFrame; - expect(obj._cacheData.sprite.width).to.equal(10); - expect(obj._cacheData.sprite.height).to.equal(11); - expect(src.toString()).to.equal(srcExpected.toString()); - expect(dest.toString()).to.equal(destExpected.toString()); + expect(obj._cacheData.sprite.width).toEqual(10); + expect(obj._cacheData.sprite.height).toEqual(11); + expect(src.toString()).toEqual(srcExpected.toString()); + expect(dest.toString()).toEqual(destExpected.toString()); } finally { @@ -71,14 +72,14 @@ describe('DisplayObject#cacheAsBitmap', function () } }); - it('should not throw error when filters is empty array', function () + it('should not throw error when filters is empty array', () => { const obj = new Container(); obj.filters = []; obj.cacheAsBitmap = true; - expect(function () + expect(() => { let renderer = null; @@ -92,10 +93,10 @@ describe('DisplayObject#cacheAsBitmap', function () { renderer.destroy(); } - }).to.not.throw(); + }).not.toThrowError(); }); - it('should respect projection', function () + it('should respect projection', () => { const par = new Container(); const obj = new Container(); @@ -107,7 +108,8 @@ describe('DisplayObject#cacheAsBitmap', function () obj.position.set(5, 15); obj.updateTransform(); obj.cacheAsBitmap = true; - obj._calculateBounds = function () + // eslint-disable-next-line func-names + obj['_calculateBounds'] = function () { this._bounds.clear(); this._bounds.addFrame(this.transform, 0, 0, 10, 11); @@ -126,10 +128,10 @@ describe('DisplayObject#cacheAsBitmap', function () const src = renderer.renderTexture.sourceFrame; const dest = renderer.renderTexture.destinationFrame; - expect(obj._cacheData.sprite.width).to.equal(10); - expect(obj._cacheData.sprite.height).to.equal(11); - expect(src.toString()).to.equal(srcExpected.toString()); - expect(dest.toString()).to.equal(destExpected.toString()); + expect(obj._cacheData.sprite.width).toEqual(10); + expect(obj._cacheData.sprite.height).toEqual(11); + expect(src.toString()).toEqual(srcExpected.toString()); + expect(dest.toString()).toEqual(destExpected.toString()); } finally { diff --git a/packages/mixin-get-child-by-name/global.d.ts b/packages/mixin-get-child-by-name/global.d.ts index 3ecfd67c4a0..aafd6b879d2 100644 --- a/packages/mixin-get-child-by-name/global.d.ts +++ b/packages/mixin-get-child-by-name/global.d.ts @@ -7,6 +7,9 @@ declare namespace GlobalMixins interface Container { - getChildByName(name: string, isRecursive?: boolean): import('@pixi/display').DisplayObject; + getChildByName( + name: string, + deep?: boolean, + ): T; } } diff --git a/packages/mixin-get-child-by-name/package.json b/packages/mixin-get-child-by-name/package.json index 5461855241e..1b0a2b1e1d6 100644 --- a/packages/mixin-get-child-by-name/package.json +++ b/packages/mixin-get-child-by-name/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/mixin-get-child-by-name", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/mixin-get-child-by-name.js", - "module": "dist/esm/mixin-get-child-by-name.js", - "bundle": "dist/browser/mixin-get-child-by-name.js", - "bundleNoExports": true, + "module": "dist/esm/mixin-get-child-by-name.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/mixin-get-child-by-name.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/mixin-get-child-by-name.js" + } + } + }, "description": "Mixin function to find a child DisplayObject by name", "author": "Mat Groves", "contributors": [ @@ -21,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/display": "6.3.0" - } + "pixiRequirements": [ + "@pixi/display" + ] } diff --git a/packages/mixin-get-child-by-name/src/index.ts b/packages/mixin-get-child-by-name/src/index.ts index fb0dbb789e8..7c103bbd45d 100644 --- a/packages/mixin-get-child-by-name/src/index.ts +++ b/packages/mixin-get-child-by-name/src/index.ts @@ -2,7 +2,6 @@ import { DisplayObject, Container } from '@pixi/display'; /** * The instance name of the object. - * * @memberof PIXI.DisplayObject# * @member {string} name */ @@ -12,14 +11,16 @@ DisplayObject.prototype.name = null; * Returns the display object in the container. * * Recursive searches are done in a preorder traversal. - * * @method getChildByName * @memberof PIXI.Container# * @param {string} name - Instance name. * @param {boolean}[deep=false] - Whether to search recursively - * @return {PIXI.DisplayObject} The child with the specified name. + * @returns {PIXI.DisplayObject} The child with the specified name. */ -Container.prototype.getChildByName = function getChildByName(name: string, deep?: boolean): DisplayObject +Container.prototype.getChildByName = function getChildByName( + name: string, + deep?: boolean, +): T { for (let i = 0, j = this.children.length; i < j; i++) { @@ -40,7 +41,7 @@ Container.prototype.getChildByName = function getChildByName(name: string, deep? continue; } - const target = (this.children[i] as Container).getChildByName(name, true); + const target = child.getChildByName(name, true); if (target) { diff --git a/packages/mixin-get-child-by-name/test/getChildByName.tests.ts b/packages/mixin-get-child-by-name/test/getChildByName.tests.ts index c97d2d098ab..cb9e78158c3 100644 --- a/packages/mixin-get-child-by-name/test/getChildByName.tests.ts +++ b/packages/mixin-get-child-by-name/test/getChildByName.tests.ts @@ -1,42 +1,44 @@ import { DisplayObject, Container } from '@pixi/display'; -import { expect } from 'chai'; import '@pixi/mixin-get-child-by-name'; -describe('DisplayObject#name', function () +describe('DisplayObject#name', () => { - it('should contain property', function () + it('should contain property', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); - expect(obj.name).to.be.not.undefined; - expect(obj.name).to.be.null; + expect(obj.name).toBeDefined(); + expect(obj.name).toBeNull(); }); }); -describe('Container#getChildByName', function () +describe('Container#getChildByName', () => { - it('should exist', function () + it('should exist', () => { const parent = new Container(); - expect(parent.getChildByName).to.be.not.undefined; - expect(parent.getChildByName).to.be.a('function'); + expect(parent.getChildByName).toBeDefined(); + expect(parent.getChildByName).toBeInstanceOf(Function); }); - it('should correctly find a child by its name', function () + it('should correctly find a child by its name', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); const parent = new Container(); obj.name = 'foo'; parent.addChild(obj); - expect(parent.getChildByName('foo')).to.equal(obj); + expect(parent.getChildByName('foo')).toEqual(obj); }); - it('should correctly find a indirect child by its name in deep search', function () + it('should correctly find a indirect child by its name in deep search', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); const parent = new Container(); const grandParent = new Container(); @@ -45,30 +47,34 @@ describe('Container#getChildByName', function () parent.addChild(obj); grandParent.addChild(parent); - expect(grandParent.getChildByName('foo', true)).to.equal(obj); + expect(grandParent.getChildByName('foo', true)).toEqual(obj); }); - it('should return null if name does not exist', function () + it('should return null if name does not exist', () => { const root = new Container(); - const displayObject = root.addChild(new DisplayObject()); - const container = root.addChild(new Container()); - expect(root.getChildByName('mock-name', true)).to.equal(null); + // @ts-expect-error - instantiating DisplayObject + root.addChild(new DisplayObject()); + root.addChild(new Container()); + + expect(root.getChildByName('mock-name', true)).toEqual(null); }); - it('should return the match highest in the hierarchy', function () + it('should return the match highest in the hierarchy', () => { const stage = new Container(); const root = stage.addChild(new Container()); const parent = root.addChild(new Container()); + // @ts-expect-error - instantiating DisplayObject const uncle = root.addChild(new DisplayObject()); + // @ts-expect-error - instantiating DisplayObject const target = new DisplayObject(); parent.name = 'mock-parent'; uncle.name = 'mock-target'; target.name = 'mock-target'; - expect(stage.getChildByName('mock-target', true)).to.equal(uncle); + expect(stage.getChildByName('mock-target', true)).toEqual(uncle); }); }); diff --git a/packages/mixin-get-global-position/package.json b/packages/mixin-get-global-position/package.json index 6a6a9f0d983..494c865f34e 100644 --- a/packages/mixin-get-global-position/package.json +++ b/packages/mixin-get-global-position/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/mixin-get-global-position", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/mixin-get-global-position.js", - "module": "dist/esm/mixin-get-global-position.js", - "bundle": "dist/browser/mixin-get-global-position.js", - "bundleNoExports": true, + "module": "dist/esm/mixin-get-global-position.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/mixin-get-global-position.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/mixin-get-global-position.js" + } + } + }, "description": "Mixin to find the global position of a DisplayObject", "author": "Mat Groves", "contributors": [ @@ -21,12 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/mixin-get-global-position/src/index.ts b/packages/mixin-get-global-position/src/index.ts index 2eb46062c38..bc2725c92e0 100644 --- a/packages/mixin-get-global-position/src/index.ts +++ b/packages/mixin-get-global-position/src/index.ts @@ -1,16 +1,15 @@ import { DisplayObject } from '@pixi/display'; -import { Point } from '@pixi/math'; +import { Point } from '@pixi/core'; /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. - * * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {PIXI.Point} [point=new PIXI.Point()] - The point to write the global value to. * @param {boolean} [skipUpdate=false] - Setting to true will stop the transforms of the scene graph from * being updated. This means the calculation returned MAY be out of date BUT will give you a * nice performance boost. - * @return {PIXI.Point} The updated point. + * @returns {PIXI.Point} The updated point. */ DisplayObject.prototype.getGlobalPosition = function getGlobalPosition(point: Point = new Point(), skipUpdate = false): Point { diff --git a/packages/mixin-get-global-position/test/getGlobalPosition.tests.ts b/packages/mixin-get-global-position/test/getGlobalPosition.tests.ts index 085495a1784..73139d328d4 100644 --- a/packages/mixin-get-global-position/test/getGlobalPosition.tests.ts +++ b/packages/mixin-get-global-position/test/getGlobalPosition.tests.ts @@ -1,19 +1,19 @@ import { Container, DisplayObject } from '@pixi/display'; -import { expect } from 'chai'; import '@pixi/mixin-get-global-position'; -describe('DisplayObject#getGlobalPosition', function () +describe('DisplayObject#getGlobalPosition', () => { - it('should exist', function () + it('should exist', () => { + // @ts-expect-error - instantiating DisplayObject const obj = new DisplayObject(); - expect(obj.getGlobalPosition).to.be.not.undefined; - expect(obj.getGlobalPosition).to.be.a('function'); + expect(obj.getGlobalPosition).toBeDefined(); + expect(obj.getGlobalPosition).toBeInstanceOf(Function); }); - it('should return correct global coordinates of a displayObject, without depending on its pivot', function () + it('should return correct global coordinates of a displayObject, without depending on its pivot', () => { const parent = new Container(); @@ -29,15 +29,15 @@ describe('DisplayObject#getGlobalPosition', function () let globalPoint = container.getGlobalPosition(); - expect(globalPoint.x).to.equal(80); - expect(globalPoint.y).to.equal(160); + expect(globalPoint.x).toEqual(80); + expect(globalPoint.y).toEqual(160); // check but skipUpdate parent.position.set(200, 200); globalPoint = container.getGlobalPosition(globalPoint, true); - expect(globalPoint.x).to.equal(80); - expect(globalPoint.y).to.equal(160); + expect(globalPoint.x).toEqual(80); + expect(globalPoint.y).toEqual(160); }); }); diff --git a/packages/particle-container/README.md b/packages/particle-container/README.md index 4c59f581948..39c3948f988 100644 --- a/packages/particle-container/README.md +++ b/packages/particle-container/README.md @@ -9,8 +9,5 @@ npm install @pixi/particle-container ## Usage ```js -import {ParticleRenderer} from '@pixi/particle-container'; -import {Renderer} from '@pixi/core'; - -Renderer.registerPlugin('particle', ParticleRenderer); +import '@pixi/particle-container'; ``` diff --git a/packages/particle-container/package.json b/packages/particle-container/package.json index 7f2c334de6f..907b13495c8 100644 --- a/packages/particle-container/package.json +++ b/packages/particle-container/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/particle-container", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/particle-container.js", - "module": "dist/esm/particle-container.js", - "bundle": "dist/browser/particle-container.js", + "module": "dist/esm/particle-container.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/particle-container.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/particle-container.js" + } + } + }, "description": "Render many sprite particles as efficiently as possible", "author": "Mat Groves", "contributors": [ @@ -20,15 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/sprite" + ] } diff --git a/packages/particle-container/src/ParticleBuffer.ts b/packages/particle-container/src/ParticleBuffer.ts index f40674932cc..4035f4dc9fd 100644 --- a/packages/particle-container/src/ParticleBuffer.ts +++ b/packages/particle-container/src/ParticleBuffer.ts @@ -1,8 +1,6 @@ -import { createIndicesForQuads } from '@pixi/utils'; -import { Geometry, Buffer } from '@pixi/core'; -import { TYPES } from '@pixi/constants'; +import { Geometry, Buffer, TYPES, utils } from '@pixi/core'; -import type { DisplayObject } from '@pixi/display'; +import type { Sprite } from '@pixi/sprite'; import type { IParticleRendererProperty } from './ParticleRenderer'; /* @@ -19,7 +17,6 @@ import type { IParticleRendererProperty } from './ParticleRenderer'; /** * The particle buffer manages the static and dynamic buffers for a particle container. - * * @private * @memberof PIXI */ @@ -109,7 +106,7 @@ export class ParticleBuffer let dynamicOffset = 0; - this.indexBuffer = new Buffer(createIndicesForQuads(this.size), true, true); + this.indexBuffer = new Buffer(utils.createIndicesForQuads(this.size), true, true); geometry.addIndex(this.indexBuffer); this.dynamicStride = 0; @@ -182,12 +179,11 @@ export class ParticleBuffer /** * Uploads the dynamic properties. - * * @param children - The children to upload. * @param startIndex - The index to start at. * @param amount - The number to upload. */ - uploadDynamic(children: DisplayObject[], startIndex: number, amount: number): void + uploadDynamic(children: Sprite[], startIndex: number, amount: number): void { for (let i = 0; i < this.dynamicProperties.length; i++) { @@ -203,12 +199,11 @@ export class ParticleBuffer /** * Uploads the static properties. - * * @param children - The children to upload. * @param startIndex - The index to start at. * @param amount - The number to upload. */ - uploadStatic(children: DisplayObject[], startIndex: number, amount: number): void + uploadStatic(children: Sprite[], startIndex: number, amount: number): void { for (let i = 0; i < this.staticProperties.length; i++) { diff --git a/packages/particle-container/src/ParticleContainer.ts b/packages/particle-container/src/ParticleContainer.ts index 02054cf47b9..27fd0219649 100644 --- a/packages/particle-container/src/ParticleContainer.ts +++ b/packages/particle-container/src/ParticleContainer.ts @@ -1,12 +1,13 @@ -import { BLEND_MODES } from '@pixi/constants'; +import { BLEND_MODES, utils } from '@pixi/core'; import { Container } from '@pixi/display'; -import { hex2rgb } from '@pixi/utils'; import type { BaseTexture, Renderer } from '@pixi/core'; import type { ParticleBuffer } from './ParticleBuffer'; import type { IDestroyOptions } from '@pixi/display'; +import type { Sprite } from '@pixi/sprite'; -export interface IParticleProperties { +export interface IParticleProperties +{ vertices?: boolean; position?: boolean; rotation?: boolean; @@ -38,22 +39,19 @@ export interface IParticleProperties { * ``` * * And here you have a hundred sprites that will be rendered at the speed of light. - * * @memberof PIXI */ -export class ParticleContainer extends Container +export class ParticleContainer extends Container { /** * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` * to reset the blend mode. - * * @default PIXI.BLEND_MODES.NORMAL */ public blendMode: BLEND_MODES; /** * If true, container allocates more batches in case there are more than `maxSize` particles. - * * @default false */ public autoResize: boolean; @@ -63,14 +61,12 @@ export class ParticleContainer extends Container * Advantages can include sharper image quality (like text) and faster rendering on canvas. * The main disadvantage is movement of objects may appear less smooth. * Default to true here as performance is usually the priority for particles. - * * @default true */ public roundPixels: boolean; /** * The texture used to render the children. - * * @readonly */ public baseTexture: BaseTexture; @@ -87,21 +83,18 @@ export class ParticleContainer extends Container /** * Set properties to be dynamic (true) / static (false). - * * @private */ _properties: boolean[]; /** * For every batch, stores _updateID corresponding to the last change in that batch. - * * @private */ _bufferUpdateIDs: number[]; /** * When child inserted, removed or changes position this number goes up. - * * @private */ _updateID: number; @@ -109,7 +102,6 @@ export class ParticleContainer extends Container /** * The tint applied to the container. * This is a hex value. A value of 0xFFFFFF will remove any tint effect. - * * @default 0xFFFFFF */ private _tint: number; @@ -164,7 +156,6 @@ export class ParticleContainer extends Container /** * Sets the private properties array to dynamic / static based on the passed properties object - * * @param properties - The properties to be uploaded */ public setProperties(properties: IParticleProperties): void @@ -191,7 +182,6 @@ export class ParticleContainer extends Container * The tint applied to the container. This is a hex value. * A value of 0xFFFFFF will remove any tint effect. * IMPORTANT: This is a WebGL only feature and will be ignored by the canvas renderer. - * * @default 0xFFFFFF */ get tint(): number @@ -202,12 +192,11 @@ export class ParticleContainer extends Container set tint(value: number) { this._tint = value; - hex2rgb(value, this.tintRgb); + utils.hex2rgb(value, this.tintRgb); } /** * Renders the container using the WebGL renderer. - * * @param renderer - The WebGL renderer. */ public render(renderer: Renderer): void @@ -219,7 +208,7 @@ export class ParticleContainer extends Container if (!this.baseTexture) { - this.baseTexture = (this.children[0] as any)._texture.baseTexture; + this.baseTexture = this.children[0]._texture.baseTexture; if (!this.baseTexture.valid) { this.baseTexture.once('update', () => this.onChildrenChange(0)); @@ -232,7 +221,6 @@ export class ParticleContainer extends Container /** * Set the flag that static data should be updated to true - * * @param smallestChildIndex - The smallest child index. */ protected onChildrenChange(smallestChildIndex: number): void @@ -261,7 +249,6 @@ export class ParticleContainer extends Container /** * Destroys the container - * * @param options - Options parameter. A boolean will act as if all options * have been set to that value * @param {boolean} [options.children=false] - if set to true, all the children will have their @@ -271,7 +258,7 @@ export class ParticleContainer extends Container * @param {boolean} [options.baseTexture=false] - Only used for child Sprites if options.children is set to true * Should it destroy the base texture of the child sprite */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { super.destroy(options); diff --git a/packages/particle-container/src/ParticleRenderer.ts b/packages/particle-container/src/ParticleRenderer.ts index dae0ad425e8..46e9bb2a2ab 100644 --- a/packages/particle-container/src/ParticleRenderer.ts +++ b/packages/particle-container/src/ParticleRenderer.ts @@ -1,16 +1,14 @@ -import { TYPES } from '@pixi/constants'; -import { ObjectRenderer, Shader, State } from '@pixi/core'; -import { Matrix } from '@pixi/math'; -import { correctBlendMode, premultiplyRgba, premultiplyTint } from '@pixi/utils'; +import { TYPES, Matrix, extensions, ExtensionType, ObjectRenderer, Shader, State, utils } from '@pixi/core'; import { ParticleBuffer } from './ParticleBuffer'; import fragment from './particles.frag'; import vertex from './particles.vert'; -import type { DisplayObject } from '@pixi/display'; import type { ParticleContainer } from './ParticleContainer'; -import type { Renderer } from '@pixi/core'; +import type { Renderer, ExtensionMetadata } from '@pixi/core'; +import type { Sprite } from '@pixi/sprite'; -export interface IParticleRendererProperty { +export interface IParticleRendererProperty +{ attributeName: string; size: number; type?: TYPES; @@ -32,11 +30,16 @@ export interface IParticleRendererProperty { /** * Renderer for Particles that is designer for speed over feature set. - * * @memberof PIXI */ export class ParticleRenderer extends ObjectRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'particle', + type: ExtensionType.RendererPlugin, + }; + /** The WebGL state in which this renderer will work. */ public readonly state: State; @@ -109,7 +112,6 @@ export class ParticleRenderer extends ObjectRenderer /** * Renders the particle container object. - * * @param container - The container to render using this ParticleRenderer. */ public render(container: ParticleContainer): void @@ -136,10 +138,11 @@ export class ParticleRenderer extends ObjectRenderer buffers = container._buffers = this.generateBuffers(container); } - const baseTexture = (children[0] as any)._texture.baseTexture; + const baseTexture = children[0]._texture.baseTexture; + const premultiplied = baseTexture.alphaMode > 0; // if the uvs have not updated then no point rendering just yet! - this.state.blendMode = correctBlendMode(container.blendMode, baseTexture.alphaMode); + this.state.blendMode = utils.correctBlendMode(container.blendMode, premultiplied); renderer.state.set(this.state); const gl = renderer.gl; @@ -150,8 +153,8 @@ export class ParticleRenderer extends ObjectRenderer this.shader.uniforms.translationMatrix = m.toArray(true); - this.shader.uniforms.uColor = premultiplyRgba(container.tintRgb, - container.worldAlpha, this.shader.uniforms.uColor, baseTexture.alphaMode); + this.shader.uniforms.uColor = utils.premultiplyRgba(container.tintRgb, + container.worldAlpha, this.shader.uniforms.uColor, premultiplied); this.shader.uniforms.uSampler = baseTexture; @@ -197,9 +200,8 @@ export class ParticleRenderer extends ObjectRenderer /** * Creates one particle buffer for each child in the container we want to render and updates internal properties. - * * @param container - The container to render using this ParticleRenderer - * @return - The buffers + * @returns - The buffers */ private generateBuffers(container: ParticleContainer): ParticleBuffer[] { @@ -218,9 +220,8 @@ export class ParticleRenderer extends ObjectRenderer /** * Creates one more particle buffer, because container has autoResize feature. - * * @param container - The container to render using this ParticleRenderer - * @return - The generated buffer + * @returns - The generated buffer */ private _generateOneMoreBuffer(container: ParticleContainer): ParticleBuffer { @@ -232,8 +233,7 @@ export class ParticleRenderer extends ObjectRenderer /** * Uploads the vertices. - * - * @param children - the array of display objects to render + * @param children - the array of sprites to render * @param startIndex - the index to start from in the children array * @param amount - the amount of children that will have their vertices uploaded * @param array - The vertices to upload. @@ -241,7 +241,7 @@ export class ParticleRenderer extends ObjectRenderer * @param offset - Offset to start at. */ public uploadVertices( - children: DisplayObject[], startIndex: number, amount: number, + children: Sprite[], startIndex: number, amount: number, array: number[], stride: number, offset: number ): void { @@ -252,7 +252,7 @@ export class ParticleRenderer extends ObjectRenderer for (let i = 0; i < amount; ++i) { - const sprite: any = children[startIndex + i]; + const sprite = children[startIndex + i]; const texture = sprite._texture; const sx = sprite.scale.x; const sy = sprite.scale.y; @@ -296,8 +296,7 @@ export class ParticleRenderer extends ObjectRenderer /** * Uploads the position. - * - * @param children - the array of display objects to render + * @param children - the array of sprites to render * @param startIndex - the index to start from in the children array * @param amount - the amount of children that will have their positions uploaded * @param array - The vertices to upload. @@ -305,7 +304,7 @@ export class ParticleRenderer extends ObjectRenderer * @param offset - Offset to start at. */ public uploadPosition( - children: DisplayObject[], startIndex: number, amount: number, + children: Sprite[], startIndex: number, amount: number, array: number[], stride: number, offset: number ): void { @@ -331,8 +330,7 @@ export class ParticleRenderer extends ObjectRenderer /** * Uploads the rotation. - * - * @param children - the array of display objects to render + * @param children - the array of sprites to render * @param startIndex - the index to start from in the children array * @param amount - the amount of children that will have their rotation uploaded * @param array - The vertices to upload. @@ -340,7 +338,7 @@ export class ParticleRenderer extends ObjectRenderer * @param offset - Offset to start at. */ public uploadRotation( - children: DisplayObject[], startIndex: number, amount: number, + children: Sprite[], startIndex: number, amount: number, array: number[], stride: number, offset: number ): void { @@ -359,8 +357,7 @@ export class ParticleRenderer extends ObjectRenderer /** * Uploads the UVs. - * - * @param children - the array of display objects to render + * @param children - the array of sprites to render * @param startIndex - the index to start from in the children array * @param amount - the amount of children that will have their rotation uploaded * @param array - The vertices to upload. @@ -368,13 +365,13 @@ export class ParticleRenderer extends ObjectRenderer * @param offset - Offset to start at. */ public uploadUvs( - children: DisplayObject[], startIndex: number, amount: number, + children: Sprite[], startIndex: number, amount: number, array: number[], stride: number, offset: number ): void { for (let i = 0; i < amount; ++i) { - const textureUvs = (children[startIndex + i] as any)._texture._uvs; + const textureUvs = children[startIndex + i]._texture._uvs; if (textureUvs) { @@ -414,8 +411,7 @@ export class ParticleRenderer extends ObjectRenderer /** * Uploads the tint. - * - * @param children - the array of display objects to render + * @param children - the array of sprites to render * @param startIndex - the index to start from in the children array * @param amount - the amount of children that will have their rotation uploaded * @param array - The vertices to upload. @@ -423,19 +419,19 @@ export class ParticleRenderer extends ObjectRenderer * @param offset - Offset to start at. */ public uploadTint( - children: DisplayObject[], startIndex: number, amount: number, + children: Sprite[], startIndex: number, amount: number, array: number[], stride: number, offset: number ): void { for (let i = 0; i < amount; ++i) { - const sprite: any = children[startIndex + i]; + const sprite = children[startIndex + i]; const premultiplied = sprite._texture.baseTexture.alphaMode > 0; const alpha = sprite.alpha; // we dont call extra function if alpha is 1.0, that's faster const argb = alpha < 1.0 && premultiplied - ? premultiplyTint(sprite._tintRGB, alpha) : sprite._tintRGB + (alpha * 255 << 24); + ? utils.premultiplyTint(sprite._tintRGB, alpha) : sprite._tintRGB + (alpha * 255 << 24); array[offset] = argb; array[offset + stride] = argb; @@ -460,3 +456,5 @@ export class ParticleRenderer extends ObjectRenderer this.tempMatrix = null; } } + +extensions.add(ParticleRenderer); diff --git a/packages/particle-container/test/ParticleContainer.tests.ts b/packages/particle-container/test/ParticleContainer.tests.ts index c593891bc5b..02cc376ea89 100644 --- a/packages/particle-container/test/ParticleContainer.tests.ts +++ b/packages/particle-container/test/ParticleContainer.tests.ts @@ -1,21 +1,20 @@ import { ParticleContainer } from '@pixi/particle-container'; import { Sprite } from '@pixi/sprite'; import { Texture } from '@pixi/core'; -import { expect } from 'chai'; -describe('ParticleContainer', function () +describe('ParticleContainer', () => { - it('should construct a container', function () + it('should construct a container', () => { const container = new ParticleContainer(); - expect(container).to.be.an.instanceOf(ParticleContainer); - expect(container.children).to.have.length(0); + expect(container).toBeInstanceOf(ParticleContainer); + expect(container.children).toHaveLength(0); container.destroy(); }); - it('should add a child', function () + it('should add a child', () => { const container = new ParticleContainer(); const child = new Sprite(Texture.WHITE); diff --git a/packages/particle-container/test/ParticleRenderer.tests.ts b/packages/particle-container/test/ParticleRenderer.tests.ts index a9f974a3fa4..7e74e0e7756 100644 --- a/packages/particle-container/test/ParticleRenderer.tests.ts +++ b/packages/particle-container/test/ParticleRenderer.tests.ts @@ -1,37 +1,26 @@ -import { ParticleContainer, ParticleRenderer } from '@pixi/particle-container'; -import { Texture, Renderer } from '@pixi/core'; -import { skipHello } from '@pixi/utils'; +import { ParticleContainer } from '@pixi/particle-container'; +import { Texture, Renderer, utils } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; -import { expect } from 'chai'; + import path from 'path'; -skipHello(); +utils.skipHello(); -describe('ParticleRenderer', function () +describe('ParticleRenderer', () => { - beforeEach(function () - { - Renderer.registerPlugin('particle', ParticleRenderer); - }); - - afterEach(function () - { - delete Renderer.__plugins.particle; - }); - - it('should render a particle container with no children', function () + it('should render a particle container with no children', () => { const renderer = new Renderer(); const container = new ParticleContainer(); - expect(container.children.length).to.equal(0); + expect(container.children.length).toEqual(0); renderer.render(container); container.destroy(); renderer.destroy(); }); - it('should render a particle container with children', function () + it('should render a particle container with children', () => { const renderer = new Renderer(); const container = new ParticleContainer(); @@ -43,7 +32,7 @@ describe('ParticleRenderer', function () renderer.destroy(); }); - it('should render a particle container with lazy texture loading', function (done: () => void) + it('should render a particle container with lazy texture loading', (done: () => void) => { const image = new Image(); @@ -51,7 +40,7 @@ describe('ParticleRenderer', function () const child = Sprite.from(image); - expect(child.texture.baseTexture.valid).to.be.false; + expect(child.texture.baseTexture.valid).toBe(false); const container = new ParticleContainer(); const renderer = new Renderer(); @@ -67,7 +56,7 @@ describe('ParticleRenderer', function () }); }); - it('should support autoResize off', function () + it('should support autoResize off', () => { const renderer = new Renderer(); const container = new ParticleContainer(1); @@ -81,7 +70,7 @@ describe('ParticleRenderer', function () renderer.destroy(); }); - it('should support autoResize on', function () + it('should support autoResize on', () => { const renderer = new Renderer(); const container = new ParticleContainer(1); diff --git a/packages/polyfill/README.md b/packages/polyfill/README.md deleted file mode 100644 index 1e880d796cb..00000000000 --- a/packages/polyfill/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# @pixi/polyfill - -Support for legacy browser JavaScript environments. Polyfills included: - -* `Math.sign` -* `Object.assign` -* `requestAnimationFrame` -* `ArrayBuffer` -* `Float32Array` -* `Uint32Array` -* `Uint16Array` - -## Installation - -```bash -npm install @pixi/polyfill -``` - -## Usage - -```js -import '@pixi/polyfill'; -``` \ No newline at end of file diff --git a/packages/polyfill/package.json b/packages/polyfill/package.json deleted file mode 100644 index 4b77aa40230..00000000000 --- a/packages/polyfill/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@pixi/polyfill", - "version": "6.3.0", - "main": "dist/cjs/polyfill.js", - "module": "dist/esm/polyfill.js", - "bundle": "dist/browser/polyfill.js", - "standalone": true, - "description": "Support for legacy browser JavaScript environments", - "author": "Mat Groves", - "contributors": [ - "Matt Karl " - ], - "homepage": "http://pixijs.com/", - "bugs": "https://github.com/pixijs/pixi.js/issues", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/pixijs/pixi.js.git" - }, - "publishConfig": { - "access": "public" - }, - "files": [ - "lib", - "dist", - "*.d.ts" - ], - "dependencies": { - "object-assign": "^4.1.1", - "promise-polyfill": "^8.2.0" - }, - "devDependencies": { - "@types/object-assign": "^4.0.30", - "@types/promise-polyfill": "^6.0.3" - } -} diff --git a/packages/polyfill/src/Math.sign.ts b/packages/polyfill/src/Math.sign.ts deleted file mode 100644 index ce78fa14ca5..00000000000 --- a/packages/polyfill/src/Math.sign.ts +++ /dev/null @@ -1,17 +0,0 @@ -// References: -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign - -if (!Math.sign) -{ - Math.sign = function mathSign(x): number - { - x = Number(x); - - if (x === 0 || isNaN(x)) - { - return x; - } - - return x > 0 ? 1 : -1; - }; -} diff --git a/packages/polyfill/src/Number.isInteger.ts b/packages/polyfill/src/Number.isInteger.ts deleted file mode 100644 index 4c20ba46118..00000000000 --- a/packages/polyfill/src/Number.isInteger.ts +++ /dev/null @@ -1,10 +0,0 @@ -// References: -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger - -if (!Number.isInteger) -{ - Number.isInteger = function numberIsInteger(value): boolean - { - return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; - }; -} diff --git a/packages/polyfill/src/Object.assign.ts b/packages/polyfill/src/Object.assign.ts deleted file mode 100644 index 2c823081434..00000000000 --- a/packages/polyfill/src/Object.assign.ts +++ /dev/null @@ -1,10 +0,0 @@ -// References: -// https://github.com/sindresorhus/object-assign -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign - -import objectAssign from 'object-assign'; - -if (!Object.assign) -{ - Object.assign = objectAssign; -} diff --git a/packages/polyfill/src/Promise.ts b/packages/polyfill/src/Promise.ts deleted file mode 100644 index bb171ba74c8..00000000000 --- a/packages/polyfill/src/Promise.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Polyfill from 'promise-polyfill'; - -// Support for IE 9 - 11 which does not include Promises -if (!globalThis.Promise) -{ - globalThis.Promise = Polyfill; -} diff --git a/packages/polyfill/src/globalThis.ts b/packages/polyfill/src/globalThis.ts deleted file mode 100644 index 3b84eec2d8c..00000000000 --- a/packages/polyfill/src/globalThis.ts +++ /dev/null @@ -1,15 +0,0 @@ -if (typeof globalThis === 'undefined') -{ - if (typeof self !== 'undefined') - { - // covers browsers - // @ts-expect-error not-writable ts(2540) error only on node - self.globalThis = self; - } - else if (typeof global !== 'undefined') - { - // covers versions of Node < 12 - // @ts-expect-error not-writable ts(2540) error only on node - global.globalThis = global; - } -} diff --git a/packages/polyfill/src/index.ts b/packages/polyfill/src/index.ts deleted file mode 100644 index a4de883281e..00000000000 --- a/packages/polyfill/src/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import './globalThis'; -import './Promise'; -import './Object.assign'; -import './requestAnimationFrame'; -import './Math.sign'; -import './Number.isInteger'; - -if (!globalThis.ArrayBuffer) -{ - (globalThis as any).ArrayBuffer = Array; -} - -if (!globalThis.Float32Array) -{ - (globalThis as any).Float32Array = Array; -} - -if (!globalThis.Uint32Array) -{ - (globalThis as any).Uint32Array = Array; -} - -if (!globalThis.Uint16Array) -{ - (globalThis as any).Uint16Array = Array; -} - -if (!globalThis.Uint8Array) -{ - (globalThis as any).Uint8Array = Array; -} - -if (!globalThis.Int32Array) -{ - (globalThis as any).Int32Array = Array; -} diff --git a/packages/polyfill/src/requestAnimationFrame.ts b/packages/polyfill/src/requestAnimationFrame.ts deleted file mode 100644 index 946b8cd2321..00000000000 --- a/packages/polyfill/src/requestAnimationFrame.ts +++ /dev/null @@ -1,79 +0,0 @@ -// References: -// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ -// https://gist.github.com/1579671 -// http://updates.html5rocks.com/2012/05/requestAnimationFrame-API-now-with-sub-millisecond-precision -// https://gist.github.com/timhall/4078614 -// https://github.com/Financial-Times/polyfill-service/tree/master/polyfills/requestAnimationFrame - -// Expected to be used with Browserfiy -// Browserify automatically detects the use of `global` and passes the -// correct reference of `global`, `globalThis`, and finally `window` - -const ONE_FRAME_TIME = 16; - -// Date.now -if (!(Date.now && Date.prototype.getTime)) -{ - Date.now = function now(): number - { - return new Date().getTime(); - }; -} - -// performance.now -if (!(globalThis.performance && globalThis.performance.now)) -{ - const startTime = Date.now(); - - if (!globalThis.performance) - { - (globalThis as any).performance = {}; - } - - globalThis.performance.now = (): number => Date.now() - startTime; -} - -// requestAnimationFrame -let lastTime = Date.now(); -const vendors = ['ms', 'moz', 'webkit', 'o']; - -for (let x = 0; x < vendors.length && !globalThis.requestAnimationFrame; ++x) -{ - const p = vendors[x]; - - globalThis.requestAnimationFrame = (globalThis as any)[`${p}RequestAnimationFrame`]; - globalThis.cancelAnimationFrame = (globalThis as any)[`${p}CancelAnimationFrame`] - || (globalThis as any)[`${p}CancelRequestAnimationFrame`]; -} - -if (!globalThis.requestAnimationFrame) -{ - globalThis.requestAnimationFrame = (callback: (...parms: any[]) => void): number => - { - if (typeof callback !== 'function') - { - throw new TypeError(`${callback}is not a function`); - } - - const currentTime = Date.now(); - let delay = ONE_FRAME_TIME + lastTime - currentTime; - - if (delay < 0) - { - delay = 0; - } - - lastTime = currentTime; - - return globalThis.self.setTimeout(() => - { - lastTime = Date.now(); - callback(performance.now()); - }, delay); - }; -} - -if (!globalThis.cancelAnimationFrame) -{ - globalThis.cancelAnimationFrame = (id: number): void => clearTimeout(id); -} diff --git a/packages/prepare/README.md b/packages/prepare/README.md index 79fb4b6f79f..f7fc0d07cc5 100644 --- a/packages/prepare/README.md +++ b/packages/prepare/README.md @@ -9,8 +9,5 @@ npm install @pixi/prepare ## Usage ```js -import { Prepare } from '@pixi/canvas-prepare'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('prepare', Prepare); +import '@pixi/canvas-prepare'; ``` \ No newline at end of file diff --git a/packages/prepare/global.d.ts b/packages/prepare/global.d.ts new file mode 100644 index 00000000000..8c68c3ac1aa --- /dev/null +++ b/packages/prepare/global.d.ts @@ -0,0 +1,7 @@ +declare namespace GlobalMixins +{ + interface Renderer + { + readonly prepare: import('@pixi/prepare').Prepare; + } +} diff --git a/packages/prepare/package.json b/packages/prepare/package.json index dd47a9860e3..1b74a3f1ea4 100644 --- a/packages/prepare/package.json +++ b/packages/prepare/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/prepare", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/prepare.js", - "module": "dist/esm/prepare.js", - "bundle": "dist/browser/prepare.js", + "module": "dist/esm/prepare.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/prepare.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/prepare.js" + } + } + }, "description": "Plugin to allow uploading textures to the GPU", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,13 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/ticker": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/graphics", + "@pixi/text" + ] } diff --git a/packages/prepare/src/BasePrepare.ts b/packages/prepare/src/BasePrepare.ts index bde8c899409..1a272de9e30 100644 --- a/packages/prepare/src/BasePrepare.ts +++ b/packages/prepare/src/BasePrepare.ts @@ -1,43 +1,44 @@ -import { Texture, BaseTexture } from '@pixi/core'; -import { Ticker, UPDATE_PRIORITY } from '@pixi/ticker'; -import { settings } from '@pixi/settings'; -import { Container, DisplayObject } from '@pixi/display'; +import { Ticker, UPDATE_PRIORITY, settings, Texture, BaseTexture } from '@pixi/core'; +import type { DisplayObject } from '@pixi/display'; +import { Container } from '@pixi/display'; import { Text, TextStyle, TextMetrics } from '@pixi/text'; import { CountLimiter } from './CountLimiter'; +import type { IRenderer } from '@pixi/core'; -import type { AbstractRenderer } from '@pixi/core'; - -interface IArrowFunction { +interface IArrowFunction +{ (): void; } -interface IUploadHook { - (helper: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended): boolean; +interface IUploadHook +{ + (helper: IRenderer | BasePrepare, item: IDisplayObjectExtended): boolean; } -interface IFindHook { +interface IFindHook +{ (item: any, queue: Array): boolean; } -export interface IDisplayObjectExtended extends DisplayObject { +export interface IDisplayObjectExtended extends DisplayObject +{ _textures?: Array; _texture?: Texture; - style?: TextStyle|Partial; + style?: TextStyle | Partial; } /** * Built-in hook to find multiple textures from objects like AnimatedSprites. - * * @private * @param item - Display object to check * @param queue - Collection of items to upload - * @return If a PIXI.Texture object was found. + * @returns If a PIXI.Texture object was found. */ function findMultipleBaseTextures(item: IDisplayObjectExtended, queue: Array): boolean { let result = false; // Objects with multiple textures - if (item && item._textures && item._textures.length) + if (item?._textures?.length) { for (let i = 0; i < item._textures.length; i++) { @@ -45,7 +46,7 @@ function findMultipleBaseTextures(item: IDisplayObjectExtended, queue: Array): boolean { @@ -71,7 +71,7 @@ function findBaseTexture(item: Texture, queue: Array): boolean { const texture = item.baseTexture; - if (queue.indexOf(texture) === -1) + if (!queue.includes(texture)) { queue.push(texture); } @@ -84,11 +84,10 @@ function findBaseTexture(item: Texture, queue: Array): boolean /** * Built-in hook to find textures from objects. - * * @private * @param item - Display object to check * @param queue - Collection of items to upload - * @return If a PIXI.Texture object was found. + * @returns If a PIXI.Texture object was found. */ function findTexture(item: IDisplayObjectExtended, queue: Array): boolean { @@ -96,7 +95,7 @@ function findTexture(item: IDisplayObjectExtended, queue: Array): boolean { const texture = item._texture.baseTexture; - if (queue.indexOf(texture) === -1) + if (!queue.includes(texture)) { queue.push(texture); } @@ -109,13 +108,12 @@ function findTexture(item: IDisplayObjectExtended, queue: Array): boolean /** * Built-in hook to draw PIXI.Text to its texture. - * * @private - * @param helper - Not used by this upload handler + * @param _helper - Not used by this upload handler * @param item - Item to check - * @return If item was uploaded. + * @returns If item was uploaded. */ -function drawText(_helper: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended): boolean +function drawText(_helper: IRenderer | BasePrepare, item: IDisplayObjectExtended): boolean { if (item instanceof Text) { @@ -130,13 +128,12 @@ function drawText(_helper: AbstractRenderer | BasePrepare, item: IDisplayObjectE /** * Built-in hook to calculate a text style for a PIXI.Text object. - * * @private - * @param helper - Not used by this upload handler + * @param _helper - Not used by this upload handler * @param item - Item to check - * @return If item was uploaded. + * @returns If item was uploaded. */ -function calculateTextStyle(_helper: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended): boolean +function calculateTextStyle(_helper: IRenderer | BasePrepare, item: IDisplayObjectExtended): boolean { if (item instanceof TextStyle) { @@ -152,30 +149,29 @@ function calculateTextStyle(_helper: AbstractRenderer | BasePrepare, item: IDisp /** * Built-in hook to find Text objects. - * * @private * @param item - Display object to check * @param queue - Collection of items to upload - * @return if a PIXI.Text object was found. + * @returns if a PIXI.Text object was found. */ function findText(item: IDisplayObjectExtended, queue: Array): boolean { if (item instanceof Text) { // push the text style to prepare it - this can be really expensive - if (queue.indexOf(item.style) === -1) + if (!queue.includes(item.style)) { queue.push(item.style); } // also push the text object so that we can render it (to canvas/texture) if needed - if (queue.indexOf(item) === -1) + if (!queue.includes(item)) { queue.push(item); } // also push the Text's texture for upload to GPU const texture = item._texture.baseTexture; - if (queue.indexOf(texture) === -1) + if (!queue.includes(texture)) { queue.push(texture); } @@ -188,17 +184,16 @@ function findText(item: IDisplayObjectExtended, queue: Array): boolean /** * Built-in hook to find TextStyle objects. - * * @private * @param item - Display object to check * @param queue - Collection of items to upload - * @return If a PIXI.TextStyle object was found. + * @returns If a PIXI.TextStyle object was found. */ function findTextStyle(item: TextStyle, queue: Array): boolean { if (item instanceof TextStyle) { - if (queue.indexOf(item) === -1) + if (!queue.includes(item)) { queue.push(item); } @@ -215,7 +210,6 @@ function findTextStyle(item: TextStyle, queue: Array): boolean * BasePrepare handles basic queuing functionality and is extended by * {@link PIXI.Prepare} and {@link PIXI.CanvasPrepare} * to provide preparation capabilities specific to their respective renderers. - * * @example * // Create a sprite * const sprite = PIXI.Sprite.from('something.png'); @@ -227,7 +221,6 @@ function findTextStyle(item: TextStyle, queue: Array): boolean * app.stage.addChild(sprite); * * }) - * * @abstract * @memberof PIXI */ @@ -240,7 +233,7 @@ export class BasePrepare private limiter: CountLimiter; /** Reference to the renderer. */ - protected renderer: AbstractRenderer; + protected renderer: IRenderer; /** * The only real difference between CanvasPrepare and Prepare is what they pass @@ -282,9 +275,9 @@ export class BasePrepare private delayedTick: IArrowFunction; /** - * @param {PIXI.AbstractRenderer} renderer - A reference to the current renderer + * @param {PIXI.IRenderer} renderer - A reference to the current renderer */ - constructor(renderer: AbstractRenderer) + constructor(renderer: IRenderer) { this.limiter = new CountLimiter(settings.UPLOADS_PER_FRAME); this.renderer = renderer; @@ -318,50 +311,42 @@ export class BasePrepare /** * Upload all the textures and graphics to the GPU. - * - * @param {Function|PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text} item - - * Either the container or display object to search for items to upload, the items to upload themselves, - * or the callback function, if items have been added using `prepare.add`. - * @param {Function} [done] - Optional callback when all queued uploads have completed + * @method PIXI.BasePrepare#upload + * @param {PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text} [item] - + * Container or display object to search for items to upload or the items to upload themselves, + * or optionally ommitted, if items have been added using {@link PIXI.BasePrepare#add `prepare.add`}. */ - upload(item: IDisplayObjectExtended | Container | BaseTexture | Texture | (() => void), done?: () => void): void + upload(item?: IDisplayObjectExtended | Container | BaseTexture | Texture): Promise { - if (typeof item === 'function') + return new Promise((resolve) => { - done = item as () => void; - item = null; - } - - // If a display object, search for items - // that we could upload - if (item) - { - this.add(item as IDisplayObjectExtended | Container | BaseTexture | Texture); - } - - // Get the items for upload from the display - if (this.queue.length) - { - if (done) + // If a display object, search for items + // that we could upload + if (item) { - this.completes.push(done); + this.add(item as IDisplayObjectExtended | Container | BaseTexture | Texture); } - if (!this.ticking) + // Get the items for upload from the display + if (this.queue.length) + { + this.completes.push(resolve); + + if (!this.ticking) + { + this.ticking = true; + Ticker.system.addOnce(this.tick, this, UPDATE_PRIORITY.UTILITY); + } + } + else { - this.ticking = true; - Ticker.system.addOnce(this.tick, this, UPDATE_PRIORITY.UTILITY); + resolve(); } - } - else if (done) - { - done(); - } + }); } /** * Handle tick update - * * @private */ tick(): void @@ -372,7 +357,6 @@ export class BasePrepare /** * Actually prepare items. This is handled outside of the tick because it will take a while * and we do NOT want to block the current animation frame from rendering. - * * @private */ prepareItems(): void @@ -426,10 +410,9 @@ export class BasePrepare /** * Adds hooks for finding items. - * * @param {Function} addHook - Function call that takes two parameters: `item:*, queue:Array` * function must return `true` if it was able to add item to the queue. - * @return Instance of plugin for chaining. + * @returns Instance of plugin for chaining. */ registerFindHook(addHook: IFindHook): this { @@ -443,10 +426,9 @@ export class BasePrepare /** * Adds hooks for uploading items. - * * @param {Function} uploadHook - Function call that takes two parameters: `prepare:CanvasPrepare, item:*` and * function must return `true` if it was able to handle upload of item. - * @return Instance of plugin for chaining. + * @returns Instance of plugin for chaining. */ registerUploadHook(uploadHook: IUploadHook): this { @@ -460,10 +442,9 @@ export class BasePrepare /** * Manually add an item to the uploading queue. - * * @param {PIXI.DisplayObject|PIXI.Container|PIXI.BaseTexture|PIXI.Texture|PIXI.Graphics|PIXI.Text|*} item - Object to * add to the queue - * @return Instance of plugin for chaining. + * @returns Instance of plugin for chaining. */ add(item: IDisplayObjectExtended | Container | BaseTexture | Texture): this { diff --git a/packages/prepare/src/CountLimiter.ts b/packages/prepare/src/CountLimiter.ts index 2dcb67c6f8b..45dc2675291 100644 --- a/packages/prepare/src/CountLimiter.ts +++ b/packages/prepare/src/CountLimiter.ts @@ -1,7 +1,6 @@ /** * CountLimiter limits the number of items handled by a {@link PIXI.BasePrepare} to a specified * number of items per frame. - * * @memberof PIXI */ export class CountLimiter @@ -9,8 +8,7 @@ export class CountLimiter /** The maximum number of items that can be prepared each frame. */ public maxItemsPerFrame: number; - /** - * The number of items that can be prepared in the current frame. */ + /** The number of items that can be prepared in the current frame. */ public itemsLeft: number; /** @@ -30,8 +28,7 @@ export class CountLimiter /** * Checks to see if another item can be uploaded. This should only be called once per item. - * - * @return If the item is allowed to be uploaded. + * @returns If the item is allowed to be uploaded. */ allowedToUpload(): boolean { diff --git a/packages/prepare/src/Prepare.ts b/packages/prepare/src/Prepare.ts index 7789ec22415..d440ea0ae27 100644 --- a/packages/prepare/src/Prepare.ts +++ b/packages/prepare/src/Prepare.ts @@ -1,18 +1,18 @@ -import { BaseTexture } from '@pixi/core'; +import { BaseTexture, extensions, ExtensionType } from '@pixi/core'; import { Graphics } from '@pixi/graphics'; -import { BasePrepare, IDisplayObjectExtended } from './BasePrepare'; +import type { IDisplayObjectExtended } from './BasePrepare'; +import { BasePrepare } from './BasePrepare'; -import type { AbstractRenderer, Renderer } from '@pixi/core'; +import type { Renderer, IRenderer, ISystem, ExtensionMetadata } from '@pixi/core'; /** * Built-in hook to upload PIXI.Texture objects to the GPU. - * * @private * @param renderer - instance of the webgl renderer * @param item - Item to check - * @return If item was uploaded. + * @returns If item was uploaded. */ -function uploadBaseTextures(renderer: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended | BaseTexture): boolean +function uploadBaseTextures(renderer: IRenderer | BasePrepare, item: IDisplayObjectExtended | BaseTexture): boolean { if (item instanceof BaseTexture) { @@ -32,13 +32,12 @@ function uploadBaseTextures(renderer: AbstractRenderer | BasePrepare, item: IDis /** * Built-in hook to upload PIXI.Graphics to the GPU. - * * @private * @param renderer - instance of the webgl renderer * @param item - Item to check - * @return If item was uploaded. + * @returns If item was uploaded. */ -function uploadGraphics(renderer: AbstractRenderer | BasePrepare, item: IDisplayObjectExtended): boolean +function uploadGraphics(renderer: IRenderer | BasePrepare, item: IDisplayObjectExtended): boolean { if (!(item instanceof Graphics)) { @@ -75,11 +74,10 @@ function uploadGraphics(renderer: AbstractRenderer | BasePrepare, item: IDisplay /** * Built-in hook to find graphics. - * * @private * @param item - Display object to check * @param queue - Collection of items to upload - * @return if a PIXI.Graphics object was found. + * @returns if a PIXI.Graphics object was found. */ function findGraphics(item: IDisplayObjectExtended, queue: Array): boolean { @@ -119,12 +117,16 @@ function findGraphics(item: IDisplayObjectExtended, queue: Array): boolean * app.renderer.plugins.prepare.upload(app.stage, () => { * app.start(); * }); - * - * * @memberof PIXI */ -export class Prepare extends BasePrepare +export class Prepare extends BasePrepare implements ISystem { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'prepare', + type: ExtensionType.RendererSystem, + }; + /** * @param {PIXI.Renderer} renderer - A reference to the current renderer */ @@ -140,3 +142,5 @@ export class Prepare extends BasePrepare this.registerUploadHook(uploadGraphics); } } + +extensions.add(Prepare); diff --git a/packages/prepare/src/TimeLimiter.ts b/packages/prepare/src/TimeLimiter.ts index 88f5c7543ba..872192b9426 100644 --- a/packages/prepare/src/TimeLimiter.ts +++ b/packages/prepare/src/TimeLimiter.ts @@ -1,7 +1,6 @@ /** * TimeLimiter limits the number of items handled by a {@link PIXI.BasePrepare} to a specified * number of milliseconds per frame. - * * @memberof PIXI */ export class TimeLimiter @@ -11,7 +10,6 @@ export class TimeLimiter /** * The start time of the current frame. - * * @readonly */ public frameStart: number; @@ -31,8 +29,7 @@ export class TimeLimiter /** * Checks to see if another item can be uploaded. This should only be called once per item. - * - * @return - If the item is allowed to be uploaded. + * @returns - If the item is allowed to be uploaded. */ allowedToUpload(): boolean { diff --git a/packages/prepare/src/settings.ts b/packages/prepare/src/settings.ts index 07a65437ac3..f4725650538 100644 --- a/packages/prepare/src/settings.ts +++ b/packages/prepare/src/settings.ts @@ -1,8 +1,7 @@ -import { settings } from '@pixi/settings'; +import { settings } from '@pixi/core'; /** * Default number of uploads per frame using prepare plugin. - * * @static * @memberof PIXI.settings * @name UPLOADS_PER_FRAME diff --git a/packages/prepare/test/BasePrepare.tests.ts b/packages/prepare/test/BasePrepare.tests.ts index 1fb0534df24..2782ea8b115 100644 --- a/packages/prepare/test/BasePrepare.tests.ts +++ b/packages/prepare/test/BasePrepare.tests.ts @@ -1,199 +1,182 @@ import { BasePrepare } from '@pixi/prepare'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import type { DisplayObject } from '@pixi/display'; +import type { IRenderer } from '@pixi/core'; -describe('BasePrepare', function () +describe('BasePrepare', () => { - it('should create a new, empty, BasePrepare', function () + it('should create a new, empty, BasePrepare', () => { - const renderer = {}; + const renderer = {} as IRenderer; const prep = new BasePrepare(renderer); - expect(prep.renderer).to.equal(renderer); - expect(prep.uploadHookHelper).to.be.null; - expect(prep.queue).to.be.empty; - expect(prep.addHooks).to.have.lengthOf(5); - expect(prep.uploadHooks).to.have.lengthOf(2); - expect(prep.completes).to.be.empty; + expect(prep['renderer']).toEqual(renderer); + expect(prep['uploadHookHelper']).toBeNull(); + expect(prep['queue']).toBeEmpty(); + expect(prep.addHooks).toHaveLength(5); + expect(prep.uploadHooks).toHaveLength(2); + expect(prep.completes).toBeEmpty(); prep.destroy(); }); - it('should add hooks', function () + it('should add hooks', () => { - function addHook() { /* empty */ } - function uploadHook() { /* empty */ } - const prep = new BasePrepare(); + function addHook() { return true; } + function uploadHook() { return true; } + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); prep.registerFindHook(addHook); prep.registerUploadHook(uploadHook); - expect(prep.addHooks).to.contain(addHook); - expect(prep.addHooks).to.have.lengthOf(6); - expect(prep.uploadHooks).to.contain(uploadHook); - expect(prep.uploadHooks).to.have.lengthOf(3); + expect(prep.addHooks).toEqual(expect.arrayContaining([addHook])); + expect(prep.addHooks).toHaveLength(6); + expect(prep.uploadHooks).toEqual(expect.arrayContaining([uploadHook])); + expect(prep.uploadHooks).toHaveLength(3); prep.destroy(); }); - it('should call hooks and complete', function () + it('should call hooks and complete', () => { - const prep = new BasePrepare(); - const uploadItem = {}; + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); + const uploadItem = {} as DisplayObject; const uploadHelper = {}; - prep.uploadHookHelper = uploadHelper; + prep['uploadHookHelper'] = uploadHelper; - const addHook = sinon.spy(function (item, queue) + const addHook = jest.fn((item, queue) => { - expect(item).to.equal(uploadItem); - expect(queue).to.equal(prep.queue); + expect(item).toEqual(uploadItem); + expect(queue).toEqual(prep['queue']); queue.push(item); return true; }); - const uploadHook = sinon.spy(function (helper, item) + const uploadHook = jest.fn((helper, item) => { - expect(helper).to.equal(uploadHelper); - expect(item).to.equal(uploadItem); + expect(helper).toEqual(uploadHelper); + expect(item).toEqual(uploadItem); return true; }); - const complete = sinon.spy(function () { /* empty */ }); prep.registerFindHook(addHook); prep.registerUploadHook(uploadHook); - prep.upload(uploadItem, complete); + prep.upload(uploadItem); - expect(prep.queue).to.contain(uploadItem); + expect(prep['queue']).toEqual(expect.arrayContaining([uploadItem])); prep.prepareItems(); - expect(addHook.calledOnce).to.be.true; - expect(uploadHook.calledOnce).to.be.true; - expect(complete.calledOnce).to.be.true; + expect(addHook).toBeCalledTimes(1); + expect(uploadHook).toBeCalledTimes(1); prep.destroy(); }); - it('should call complete if no queue', function () + it('should call complete if no queue', async () => { - const prep = new BasePrepare(); + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); function addHook() { return false; } - const complete = sinon.spy(function () { /* empty */ }); + const complete = jest.fn(() => { /* empty */ }); prep.registerFindHook(addHook); - prep.upload({}, complete); + await prep.upload({} as DisplayObject).then(complete); - expect(complete.calledOnce).to.be.true; + expect(complete).toBeCalledTimes(1); prep.destroy(); }); - it('should remove un-preparable items from queue', function () + it('should remove un-preparable items from queue', () => { - const prep = new BasePrepare(); + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); - const addHook = sinon.spy(function (item, queue) + const addHook = jest.fn((item, queue) => { queue.push(item); return true; }); - const uploadHook = sinon.spy(function () - { - return false; - }); - const complete = sinon.spy(function () { /* empty */ }); + const uploadHook = jest.fn(() => + false); prep.registerFindHook(addHook); prep.registerUploadHook(uploadHook); - prep.upload({}, complete); + prep.upload({} as DisplayObject); - expect(prep.queue).to.have.lengthOf(1); + expect(prep['queue']).toHaveLength(1); prep.prepareItems(); - expect(prep.queue).to.be.empty; - expect(addHook.calledOnce).to.be.true; - expect(uploadHook.calledOnce).to.be.true; - expect(complete.calledOnce).to.be.true; + expect(prep['queue']).toBeEmpty(); + expect(addHook).toBeCalledTimes(1); + expect(uploadHook).toBeCalledTimes(1); prep.destroy(); }); - it('should remove destroyed items from queue', function () + it('should remove destroyed items from queue', () => { - const prep = new BasePrepare(); + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); - const addHook = sinon.spy(function (item, queue) + const addHook = jest.fn((item, queue) => { queue.push(item); return true; }); - const uploadHook = sinon.spy(function () - { - return false; - }); - const complete = sinon.spy(function () { /* empty */ }); + const uploadHook = jest.fn(() => + false); prep.registerFindHook(addHook); prep.registerUploadHook(uploadHook); - const item = {}; + const item = {} as DisplayObject; - prep.upload(item, complete); + prep.upload(item); - expect(prep.queue).to.have.lengthOf(1); + expect(prep['queue']).toHaveLength(1); - item._destroyed = true; + item['_destroyed'] = true; prep.prepareItems(); - expect(prep.queue).to.be.empty; - expect(addHook.calledOnce).to.be.true; - expect(uploadHook.called).to.be.false; - expect(complete.calledOnce).to.be.true; + expect(prep['queue']).toBeEmpty(); + expect(addHook).toBeCalledTimes(1); + expect(uploadHook).not.toHaveBeenCalled(); prep.destroy(); }); - it('should attach to the system ticker', function (done) + it('should attach to the system ticker', async () => { - const prep = new BasePrepare(); + const renderer = {} as IRenderer; + const prep = new BasePrepare(renderer); - const addHook = sinon.spy(function (item, queue) + const addHook = jest.fn((item, queue) => { queue.push(item); return true; }); - const uploadHook = sinon.spy(function () - { - return true; - }); - - function complete() - { - expect(prep.queue).to.be.empty; - expect(addHook.calledOnce).to.be.true; - expect(uploadHook.calledOnce).to.be.true; - - prep.destroy(); - - done(); - } + const uploadHook = jest.fn(() => true); prep.registerFindHook(addHook); prep.registerUploadHook(uploadHook); - prep.upload({}, complete); + await prep.upload({} as DisplayObject); - expect(prep.queue).to.have.lengthOf(1); - expect(addHook.called).to.be.true; - expect(uploadHook.called).to.be.false; - expect(complete.called).to.not.be.ok; + expect(prep['queue']).toBeEmpty(); + expect(addHook).toBeCalledTimes(1); + expect(uploadHook).toBeCalledTimes(1); + + prep.destroy(); }); }); diff --git a/packages/prepare/test/CountLimiter.tests.ts b/packages/prepare/test/CountLimiter.tests.ts index 3d5a8c8949b..14728671215 100644 --- a/packages/prepare/test/CountLimiter.tests.ts +++ b/packages/prepare/test/CountLimiter.tests.ts @@ -1,22 +1,21 @@ import { CountLimiter } from '@pixi/prepare'; -import { expect } from 'chai'; -describe('CountLimiter', function () +describe('CountLimiter', () => { - it('should limit to specified number per beginFrame()', function () + it('should limit to specified number per beginFrame()', () => { const limit = new CountLimiter(3); limit.beginFrame(); - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.false; + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(false); limit.beginFrame(); - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.true; - expect(limit.allowedToUpload()).to.be.false; + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(true); + expect(limit.allowedToUpload()).toBe(false); }); }); diff --git a/packages/prepare/test/Prepare.tests.ts b/packages/prepare/test/Prepare.tests.ts index a89b05efaa6..9ffc89c0c95 100644 --- a/packages/prepare/test/Prepare.tests.ts +++ b/packages/prepare/test/Prepare.tests.ts @@ -2,11 +2,10 @@ import { Prepare } from '@pixi/prepare'; import { Renderer, Texture } from '@pixi/core'; import { Container } from '@pixi/display'; import { Graphics } from '@pixi/graphics'; -import { expect } from 'chai'; -describe('Prepare', function () +describe('Prepare', () => { - it('should upload graphics vao and textures', function () + it('should upload graphics vao and textures', () => { const renderer = new Renderer({ width: 1, height: 1 }); const prepare = new Prepare(renderer); @@ -28,16 +27,16 @@ describe('Prepare', function () graphics.drawRect(0, 0, 10, 10); graphics.beginTextureFill({ texture }); graphics.drawRect(20, 20, 10, 10); - graphics.geometry.isBatchable = function () { return false; }; + graphics.geometry['isBatchable'] = () => false; container.addChild(graphics); prepare.add(container); prepare.prepareItems(); - expect(Object.keys(texture.baseTexture._glTextures)).to.eql([`${CONTEXT_UID}`]); - expect(graphics.geometry.batches.length).to.equal(2); - expect(vaos[CONTEXT_UID]).to.exist; - expect(Object.keys(vaos[CONTEXT_UID]).length).to.equal(2); // [shader_id] and [signature] + expect(Object.keys(texture.baseTexture._glTextures)).toEqual([`${CONTEXT_UID}`]); + expect(graphics.geometry.batches.length).toEqual(2); + expect(vaos[CONTEXT_UID]).toBeDefined(); + expect(Object.keys(vaos[CONTEXT_UID]).length).toEqual(2); // [shader_id] and [signature] } finally { diff --git a/packages/prepare/test/TimeLimiter.tests.ts b/packages/prepare/test/TimeLimiter.tests.ts index 467ff7f6bda..0e55cb19e7d 100644 --- a/packages/prepare/test/TimeLimiter.tests.ts +++ b/packages/prepare/test/TimeLimiter.tests.ts @@ -1,27 +1,25 @@ import { TimeLimiter } from '@pixi/prepare'; -import { expect } from 'chai'; -describe('TimeLimiter', function () +describe('TimeLimiter', () => { + // eslint-disable-next-line func-names it('should limit to stop after time from beginFrame()', function (done) { - this.slow(500); - const limit = new TimeLimiter(100); limit.beginFrame(); for (let i = 0; i < 20; ++i) { - expect(limit.allowedToUpload()).to.be.true; + expect(limit.allowedToUpload()).toBe(true); } - setTimeout(function () + setTimeout(() => { - expect(limit.allowedToUpload()).to.be.false; + expect(limit.allowedToUpload()).toBe(false); limit.beginFrame(); - expect(limit.allowedToUpload()).to.be.true; + expect(limit.allowedToUpload()).toBe(true); done(); }, 200); diff --git a/packages/runner/package.json b/packages/runner/package.json index 69a94e1e92e..4e3fb6c0a63 100644 --- a/packages/runner/package.json +++ b/packages/runner/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/runner", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/runner.js", - "module": "dist/esm/runner.js", - "bundle": "dist/browser/runner.js", + "module": "dist/esm/runner.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/runner.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/runner.js" + } + } + }, "description": "A simple alternative to events and signals with an emphasis on performance.", "author": "Mat Groves", "contributors": [ @@ -35,7 +47,6 @@ "benchmark": "cd benchmark && npm start" }, "files": [ - "lib", "dist", "*.d.ts" ] diff --git a/packages/runner/src/Runner.ts b/packages/runner/src/Runner.ts index c90c99884c9..0cfedaaedbc 100644 --- a/packages/runner/src/Runner.ts +++ b/packages/runner/src/Runner.ts @@ -40,7 +40,6 @@ * * myGame.update.emit(time); * ``` - * * @memberof PIXI */ export class Runner @@ -59,11 +58,12 @@ export class Runner this._aliasCount = 0; } + /* eslint-disable jsdoc/require-param, jsdoc/check-param-names */ /** * Dispatch/Broadcast Runner to all listeners added to the queue. - * * @param {...any} params - (optional) parameters to pass to each listener */ + /* eslint-enable jsdoc/require-param, jsdoc/check-param-names */ public emit(a0?: unknown, a1?: unknown, a2?: unknown, a3?: unknown, a4?: unknown, a5?: unknown, a6?: unknown, a7?: unknown): this { @@ -114,7 +114,6 @@ export class Runner * ``` * * The scope used will be the object itself. - * * @param {any} item - The object that will be listening. */ public add(item: unknown): this @@ -131,7 +130,6 @@ export class Runner /** * Remove a single listener from the dispatch queue. - * * @param {any} item - The listener that you would like to remove. */ public remove(item: unknown): this @@ -149,12 +147,11 @@ export class Runner /** * Check to see if the listener is already in the Runner - * * @param {any} item - The listener that you would like to check. */ public contains(item: unknown): boolean { - return this.items.indexOf(item) !== -1; + return this.items.includes(item); } /** Remove all listeners from the Runner */ @@ -176,7 +173,6 @@ export class Runner /** * `true` if there are no this Runner contains no listeners - * * @readonly */ public get empty(): boolean @@ -186,7 +182,6 @@ export class Runner /** * The name of the runner. - * * @readonly */ public get name(): string diff --git a/packages/runner/test/Runner.tests.ts b/packages/runner/test/Runner.tests.ts index 7c4b88cb181..09f31d7f864 100644 --- a/packages/runner/test/Runner.tests.ts +++ b/packages/runner/test/Runner.tests.ts @@ -1,39 +1,38 @@ import { Runner } from '@pixi/runner'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('Runner', function () +describe('Runner', () => { - it('should should exist', function () + it('should should exist', () => { - expect(Runner).to.be.not.undefined; - expect(typeof Runner).to.equal('function'); + expect(Runner).toBeDefined(); + expect(typeof Runner).toEqual('function'); }); - it('should implement emit', function () + it('should implement emit', () => { const complete = new Runner('complete'); - expect(complete.name).to.equal('complete'); - const callback = sinon.spy(); + expect(complete.name).toEqual('complete'); + const callback = jest.fn(); complete.add({ complete: callback }); complete.emit(); - expect(callback.called).to.be.true; - expect(callback.calledOnce).to.be.true; + expect(callback).toBeCalled(); + expect(callback).toBeCalledTimes(1); complete.emit(); - expect(callback.calledTwice).to.be.true; + expect(callback).toBeCalledTimes(2); complete.emit(); - expect(callback.calledThrice).to.be.true; + expect(callback).toBeCalledTimes(3); complete.destroy(); - expect(!complete.items).to.be.true; - expect(!complete.name).to.be.true; + expect(!complete.items).toBe(true); + expect(!complete.name).toBe(true); }); - it('should implement emit with arguments', function () + it('should implement emit with arguments', () => { const update = new Runner('update'); - const callback = sinon.spy(function (time, delta) + // eslint-disable-next-line func-names + const callback = jest.fn(function (time, delta) { let len = 0; // Count the number of non-undefined arguments @@ -46,68 +45,69 @@ describe('Runner', function () len++; } } - expect(len).to.equal(2); - expect(time).to.equal(1); - expect(delta).to.equal(2); + expect(len).toEqual(2); + expect(time).toEqual(1); + expect(delta).toEqual(2); }); update.add({ update: callback }); update.emit(1, 2); - expect(callback.called).to.be.true; - expect(callback.calledOnce).to.be.true; + expect(callback).toBeCalled(); + expect(callback).toBeCalledTimes(1); }); - it('should throw an error with too many arguments', function () + it('should throw an error with too many arguments', () => { const complete = new Runner('complete'); complete.add({ - // eslint-disable-next-line no-unused-vars, no-empty-function - complete(a, b, c, d, e, f, g, h, i) {}, + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function + complete(_a: any, _b: any, _c: any, _d: any, _e: any, _f: any, _g: any, _h: any, _i: any) {}, }); try { + // @ts-expect-error - testing to many arguments complete.emit(1, 2, 3, 4, 5, 6, 7, 8, 9); throw new Error('failed too many args'); } catch (e) { - expect(!!e).to.be.true; - expect(e.message).to.equal('max arguments reached'); + expect(!!e).toBe(true); + expect((e as Error).message).toEqual('max arguments reached'); } }); - it('should implement multiple targets', function () + it('should implement multiple targets', () => { const complete = new Runner('complete'); - const obj = { complete: sinon.spy() }; - const obj2 = { complete: sinon.spy() }; + const obj = { complete: jest.fn() }; + const obj2 = { complete: jest.fn() }; - expect(complete.empty).to.be.true; + expect(complete.empty).toBe(true); complete.add(obj); - expect(complete.contains(obj)).to.be.true; + expect(complete.contains(obj)).toBe(true); complete.add(obj2); - expect(complete.contains(obj2)).to.be.true; + expect(complete.contains(obj2)).toBe(true); complete.emit(); - expect(!complete.empty).to.be.true; - expect(complete.items.length).to.equal(2); - expect(obj.complete.called).to.be.true; - expect(obj.complete.calledOnce).to.be.true; - expect(obj2.complete.called).to.be.true; - expect(obj2.complete.calledOnce).to.be.true; + expect(!complete.empty).toBe(true); + expect(complete.items.length).toEqual(2); + expect(obj.complete).toBeCalled(); + expect(obj.complete).toBeCalledTimes(1); + expect(obj2.complete).toBeCalled(); + expect(obj2.complete).toBeCalledTimes(1); complete.remove(obj); - expect(complete.items.length).to.equal(1); + expect(complete.items.length).toEqual(1); complete.remove(obj2); - expect(complete.items.length).to.equal(0); - expect(complete.empty).to.be.true; + expect(complete.items.length).toEqual(0); + expect(complete.empty).toBe(true); }); - it('should implement removeAll', function () + it('should implement removeAll', () => { const complete = new Runner('complete'); - // eslint-disable-next-line no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function const obj = { complete() {} }; - // eslint-disable-next-line no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function const obj2 = { complete() {} }; const obj3 = {}; @@ -116,23 +116,23 @@ describe('Runner', function () .add(obj2) .add(obj3); - expect(complete.items.length).to.equal(2); + expect(complete.items.length).toEqual(2); complete.removeAll(); - expect(complete.empty).to.be.true; + expect(complete.empty).toBe(true); }); - it('should not add items more than once', function () + it('should not add items more than once', () => { const complete = new Runner('complete'); - // eslint-disable-next-line no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function const obj = { complete() {} }; complete.add(obj).add(obj); - expect(complete.items.length).to.equal(1); + expect(complete.items.length).toEqual(1); }); - it('should not not bug out is items are removed items whilst mid run', function () + it('should not not bug out is items are removed items whilst mid run', () => { const complete = new Runner('complete'); @@ -141,12 +141,15 @@ describe('Runner', function () for (let i = 0; i < 10; i++) { - // eslint-disable-next-line no-loop-func - const obj = { complete() - { - tick++; - complete.remove(obj); - } }; + const obj = { + id: 0, + // eslint-disable-next-line no-loop-func + complete() + { + tick++; + complete.remove(obj); + } + }; obj.id = i; objs.push(obj); @@ -154,9 +157,9 @@ describe('Runner', function () complete.add(obj); } - complete.run(); + complete.emit(); - expect(complete.items.length).to.equal(0); - expect(tick).to.equal(10); + expect(complete.items.length).toEqual(0); + expect(tick).toEqual(10); }); }); diff --git a/packages/settings/package.json b/packages/settings/package.json index 895bda2bf4e..3123f9eadfc 100644 --- a/packages/settings/package.json +++ b/packages/settings/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/settings", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/settings.js", - "module": "dist/esm/settings.js", - "bundle": "dist/browser/settings.js", + "module": "dist/esm/settings.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/settings.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/settings.js" + } + } + }, "description": "Collecting of user configurable settings used throughout PixiJS", "author": "Mat Groves", "contributors": [ @@ -20,11 +32,10 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "dependencies": { + "devDependencies": { "ismobilejs": "^1.1.0" } } diff --git a/packages/settings/src/adapter.ts b/packages/settings/src/adapter.ts new file mode 100644 index 00000000000..d4078781cb4 --- /dev/null +++ b/packages/settings/src/adapter.ts @@ -0,0 +1,41 @@ +export type ContextIds = '2d' | 'webgl' | 'experimental-webgl' | 'webgl2'; + +/** + * This interface describes all the DOM dependent calls that Pixi makes throughout its codebase + * Implementations of this interface can be used to make sure Pixi will work in any environment + * such as browser, web workers, and node + */ +export interface IAdapter +{ + /** Returns a canvas object that can be used to create a webgl context. */ + createCanvas: (width?: number, height?: number) => HTMLCanvasElement; + /** Returns a webgl rendering context. */ + getWebGLRenderingContext: () => typeof WebGLRenderingContext; + /** Returns a partial implementation of the browsers window.navigator */ + getNavigator: () => { userAgent: string }; + /** Returns the current base URL For browser environments this is either the document.baseURI or window.location.href */ + getBaseUrl: () => string; + fetch: (url: RequestInfo, options?: RequestInit) => Promise; +} + +export const BrowserAdapter = { + /** + * Creates a canvas element of the given size. + * This canvas is created using the browser's native canvas element. + * @param width - width of the canvas + * @param height - height of the canvas + */ + createCanvas: (width: number, height: number): HTMLCanvasElement => + { + const canvas = document.createElement('canvas'); + + canvas.width = width; + canvas.height = height; + + return canvas; + }, + getWebGLRenderingContext: () => WebGLRenderingContext, + getNavigator: () => navigator, + getBaseUrl: () => (document.baseURI ?? window.location.href), + fetch: (url: RequestInfo, options?: RequestInit) => fetch(url, options), +} as IAdapter; diff --git a/packages/settings/src/index.ts b/packages/settings/src/index.ts index fa8982fbd45..4fcf3d37264 100644 --- a/packages/settings/src/index.ts +++ b/packages/settings/src/index.ts @@ -1,2 +1,3 @@ export * from './settings'; export * from './utils/isMobile'; +export * from './adapter'; diff --git a/packages/settings/src/settings.ts b/packages/settings/src/settings.ts index eb09d3702fd..d38a234b345 100644 --- a/packages/settings/src/settings.ts +++ b/packages/settings/src/settings.ts @@ -1,10 +1,13 @@ +import type { ENV } from '@pixi/constants'; +import { GC_MODES, MIPMAP_MODES, MSAA_QUALITY, PRECISION, SCALE_MODES, WRAP_MODES } from '@pixi/constants'; +import type { IAdapter } from './adapter'; +import { BrowserAdapter } from './adapter'; +import { canUploadSameBuffer } from './utils/canUploadSameBuffer'; import { isMobile } from './utils/isMobile'; import { maxRecommendedTextures } from './utils/maxRecommendedTextures'; -import { canUploadSameBuffer } from './utils/canUploadSameBuffer'; -import { GC_MODES, MIPMAP_MODES, MSAA_QUALITY, PRECISION, SCALE_MODES, WRAP_MODES } from '@pixi/constants'; -import type { ENV } from '@pixi/constants'; -export interface IRenderOptions { +export interface IRenderOptions +{ view: HTMLCanvasElement; antialias: boolean; autoDensity: boolean; @@ -18,7 +21,9 @@ export interface IRenderOptions { legacy: boolean; } -export interface ISettings { +export interface ISettings +{ + ADAPTER: IAdapter; MIPMAP_TEXTURES: MIPMAP_MODES; ANISOTROPIC_LEVEL: number; RESOLUTION: number; @@ -61,10 +66,22 @@ export interface ISettings { */ export const settings: ISettings = { + /** + * This adapter is used to call methods that are platform dependent. + * For example `document.createElement` only runs on the web but fails in node environments. + * This allows us to support more platforms by abstracting away specific implementations per platform. + * + * By default the adapter is set to work in the browser. However you can create your own + * by implementing the `IAdapter` interface. See `IAdapter` for more information. + * @name ADAPTER + * @memberof PIXI.settings + * @type {PIXI.IAdapter} + * @default PIXI.BrowserAdapter + */ + ADAPTER: BrowserAdapter, /** * If set to true WebGL will attempt make textures mimpaped by default. * Mipmapping will only succeed if the base texture uploaded has power of two dimensions. - * * @static * @name MIPMAP_TEXTURES * @memberof PIXI.settings @@ -76,7 +93,6 @@ export const settings: ISettings = { /** * Default anisotropic filtering level of textures. * Usually from 0 to 16 - * * @static * @name ANISOTROPIC_LEVEL * @memberof PIXI.settings @@ -87,7 +103,6 @@ export const settings: ISettings = { /** * Default resolution / device pixel ratio of the renderer. - * * @static * @name RESOLUTION * @memberof PIXI.settings @@ -98,7 +113,6 @@ export const settings: ISettings = { /** * Default filter resolution. - * * @static * @name FILTER_RESOLUTION * @memberof PIXI.settings @@ -109,7 +123,6 @@ export const settings: ISettings = { /** * Default filter samples. - * * @static * @name FILTER_MULTISAMPLE * @memberof PIXI.settings @@ -120,7 +133,6 @@ export const settings: ISettings = { /** * The maximum textures that this device supports. - * * @static * @name SPRITE_MAX_TEXTURES * @memberof PIXI.settings @@ -136,7 +148,6 @@ export const settings: ISettings = { * The default sprite batch size. * * The default aims to balance desktop and mobile devices. - * * @static * @name SPRITE_BATCH_SIZE * @memberof PIXI.settings @@ -148,22 +159,21 @@ export const settings: ISettings = { /** * The default render options if none are supplied to {@link PIXI.Renderer} * or {@link PIXI.CanvasRenderer}. - * * @static * @name RENDER_OPTIONS * @memberof PIXI.settings * @type {object} - * @property {HTMLCanvasElement} view=null - * @property {boolean} antialias=false - * @property {boolean} autoDensity=false - * @property {boolean} useContextAlpha=true - * @property {number} backgroundColor=0x000000 - * @property {number} backgroundAlpha=1 - * @property {boolean} clearBeforeRender=true - * @property {boolean} preserveDrawingBuffer=false - * @property {number} width=800 - * @property {number} height=600 - * @property {boolean} legacy=false + * @property {HTMLCanvasElement} [view=null] - + * @property {boolean} [antialias=false] - + * @property {boolean} [autoDensity=false] - + * @property {boolean} [useContextAlpha=true] - + * @property {number} [backgroundColor=0x000000] - + * @property {number} [backgroundAlpha=1] - + * @property {boolean} [clearBeforeRender=true] - + * @property {boolean} [preserveDrawingBuffer=false] - + * @property {number} [width=800] - + * @property {number} [height=600] - + * @property {boolean} [legacy=false] - */ RENDER_OPTIONS: { view: null, @@ -181,7 +191,6 @@ export const settings: ISettings = { /** * Default Garbage Collection mode. - * * @static * @name GC_MODE * @memberof PIXI.settings @@ -192,7 +201,6 @@ export const settings: ISettings = { /** * Default Garbage Collection max idle. - * * @static * @name GC_MAX_IDLE * @memberof PIXI.settings @@ -203,7 +211,6 @@ export const settings: ISettings = { /** * Default Garbage Collection maximum check count. - * * @static * @name GC_MAX_CHECK_COUNT * @memberof PIXI.settings @@ -214,7 +221,6 @@ export const settings: ISettings = { /** * Default wrap modes that are supported by pixi. - * * @static * @name WRAP_MODE * @memberof PIXI.settings @@ -225,7 +231,6 @@ export const settings: ISettings = { /** * Default scale mode for textures. - * * @static * @name SCALE_MODE * @memberof PIXI.settings @@ -236,7 +241,6 @@ export const settings: ISettings = { /** * Default specify float precision in vertex shader. - * * @static * @name PRECISION_VERTEX * @memberof PIXI.settings @@ -248,7 +252,6 @@ export const settings: ISettings = { /** * Default specify float precision in fragment shader. * iOS is best set at highp due to https://github.com/pixijs/pixi.js/issues/3742 - * * @static * @name PRECISION_FRAGMENT * @memberof PIXI.settings @@ -259,7 +262,6 @@ export const settings: ISettings = { /** * Can we upload the same buffer in a single frame? - * * @static * @name CAN_UPLOAD_SAME_BUFFER * @memberof PIXI.settings @@ -269,7 +271,6 @@ export const settings: ISettings = { /** * Enables bitmap creation before image load. This feature is experimental. - * * @static * @name CREATE_IMAGE_BITMAP * @memberof PIXI.settings @@ -282,7 +283,6 @@ export const settings: ISettings = { * If true PixiJS will Math.floor() x/y values when rendering, stopping pixel interpolation. * Advantages can include sharper image quality (like text) and faster rendering on canvas. * The main disadvantage is movement of objects may appear less smooth. - * * @static * @constant * @memberof PIXI.settings diff --git a/packages/settings/src/utils/canUploadSameBuffer.ts b/packages/settings/src/utils/canUploadSameBuffer.ts index c2706314a26..778c77c4564 100644 --- a/packages/settings/src/utils/canUploadSameBuffer.ts +++ b/packages/settings/src/utils/canUploadSameBuffer.ts @@ -4,9 +4,8 @@ import { isMobile } from './isMobile'; * Uploading the same buffer multiple times in a single frame can cause performance issues. * Apparent on iOS so only check for that at the moment * This check may become more complex if this issue pops up elsewhere. - * * @private - * @returns {boolean} + * @returns {boolean} `true` if the same buffer may be uploaded more than once. */ export function canUploadSameBuffer(): boolean { diff --git a/packages/settings/src/utils/isMobile.ts b/packages/settings/src/utils/isMobile.ts index 1b4bb868193..dc6867ed335 100644 --- a/packages/settings/src/utils/isMobile.ts +++ b/packages/settings/src/utils/isMobile.ts @@ -1,9 +1,39 @@ -// The ESM/CJS versions of ismobilejs only -// exports the function for executing -// designed for Node-only environments import isMobileCall from 'ismobilejs'; -import type { isMobileResult } from 'ismobilejs'; -const isMobile: isMobileResult = isMobileCall(globalThis.navigator); +type isMobileResult = { + apple: { + phone: boolean; + ipod: boolean; + tablet: boolean; + universal: boolean; + device: boolean; + }; + amazon: { + phone: boolean; + tablet: boolean; + device: boolean; + }; + android: { + phone: boolean; + tablet: boolean; + device: boolean; + }; + windows: { + phone: boolean; + tablet: boolean; + device: boolean; + }; + other: { + blackberry: boolean; + blackberry10: boolean; + opera: boolean; + firefox: boolean; + chrome: boolean; + device: boolean; + }; + phone: boolean; + tablet: boolean; + any: boolean; +}; -export { isMobile }; +export const isMobile: isMobileResult = isMobileCall(globalThis.navigator); diff --git a/packages/settings/src/utils/maxRecommendedTextures.ts b/packages/settings/src/utils/maxRecommendedTextures.ts index 0eb88fd526b..e3482e31ffc 100644 --- a/packages/settings/src/utils/maxRecommendedTextures.ts +++ b/packages/settings/src/utils/maxRecommendedTextures.ts @@ -8,10 +8,9 @@ import { isMobile } from './isMobile'; * * In v4, all mobile devices were limited to 4 texture units because for this. * In v5, we allow all texture units to be used on modern Apple or Android devices. - * * @private * @param {number} max - * @returns {number} + * @returns {number} The maximum recommended texture units to use. */ export function maxRecommendedTextures(max: number): number { diff --git a/packages/settings/test/settings.tests.ts b/packages/settings/test/settings.tests.ts index 82a22abf4ff..1d9da16d537 100644 --- a/packages/settings/test/settings.tests.ts +++ b/packages/settings/test/settings.tests.ts @@ -1,80 +1,80 @@ import { settings } from '@pixi/settings'; -import { expect } from 'chai'; +import '@pixi/core'; -describe('settings', function () +describe('settings', () => { - it('should have MIPMAP_TEXTURES', function () + it('should have MIPMAP_TEXTURES', () => { - expect(settings.MIPMAP_TEXTURES).to.be.a('number'); + expect(settings.MIPMAP_TEXTURES).toBeNumber(); }); - it('should have RESOLUTION', function () + it('should have RESOLUTION', () => { - expect(settings.RESOLUTION).to.be.a('number'); + expect(settings.RESOLUTION).toBeNumber(); }); - it('should have PREFER_ENV', function () + it('should have PREFER_ENV', () => { - expect(settings.PREFER_ENV).to.be.a('number'); + expect(settings.PREFER_ENV).toBeNumber(); }); - it('should have FILTER_RESOLUTION', function () + it('should have FILTER_RESOLUTION', () => { - expect(settings.FILTER_RESOLUTION).to.be.a('number'); + expect(settings.FILTER_RESOLUTION).toBeNumber(); }); - it('should have SPRITE_MAX_TEXTURES', function () + it('should have SPRITE_MAX_TEXTURES', () => { - expect(settings.SPRITE_MAX_TEXTURES).to.be.a('number'); + expect(settings.SPRITE_MAX_TEXTURES).toBeNumber(); }); - it('should have SPRITE_BATCH_SIZE', function () + it('should have SPRITE_BATCH_SIZE', () => { - expect(settings.SPRITE_BATCH_SIZE).to.be.a('number'); + expect(settings.SPRITE_BATCH_SIZE).toBeNumber(); }); - it('should have RENDER_OPTIONS', function () + it('should have RENDER_OPTIONS', () => { - expect(settings.RENDER_OPTIONS).to.be.an('object'); + expect(settings.RENDER_OPTIONS).toBeObject(); }); - it('should have GC_MODE', function () + it('should have GC_MODE', () => { - expect(settings.GC_MODE).to.be.a('number'); + expect(settings.GC_MODE).toBeNumber(); }); - it('should have GC_MAX_IDLE', function () + it('should have GC_MAX_IDLE', () => { - expect(settings.GC_MAX_IDLE).to.be.a('number'); + expect(settings.GC_MAX_IDLE).toBeNumber(); }); - it('should have GC_MAX_CHECK_COUNT', function () + it('should have GC_MAX_CHECK_COUNT', () => { - expect(settings.GC_MAX_CHECK_COUNT).to.be.a('number'); + expect(settings.GC_MAX_CHECK_COUNT).toBeNumber(); }); - it('should have WRAP_MODE', function () + it('should have WRAP_MODE', () => { - expect(settings.WRAP_MODE).to.be.a('number'); + expect(settings.WRAP_MODE).toBeNumber(); }); - it('should have SCALE_MODE', function () + it('should have SCALE_MODE', () => { - expect(settings.SCALE_MODE).to.be.a('number'); + expect(settings.SCALE_MODE).toBeNumber(); }); - it('should have PRECISION_VERTEX', function () + it('should have PRECISION_VERTEX', () => { - expect(settings.PRECISION_VERTEX).to.be.a.string; + expect(settings.PRECISION_VERTEX).toBeString(); }); - it('should have PRECISION_FRAGMENT', function () + it('should have PRECISION_FRAGMENT', () => { - expect(settings.PRECISION_FRAGMENT).to.be.a.string; + expect(settings.PRECISION_FRAGMENT).toBeString(); }); - it('should have CAN_UPLOAD_SAME_BUFFER', function () + it('should have CAN_UPLOAD_SAME_BUFFER', () => { - expect(settings.CAN_UPLOAD_SAME_BUFFER).to.be.a('boolean'); + expect(settings.CAN_UPLOAD_SAME_BUFFER).toBeBoolean(); }); }); diff --git a/packages/sprite-animated/package.json b/packages/sprite-animated/package.json index ee1049cea61..4309ed6b1d8 100644 --- a/packages/sprite-animated/package.json +++ b/packages/sprite-animated/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/sprite-animated", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/sprite-animated.js", - "module": "dist/esm/sprite-animated.js", - "bundle": "dist/browser/sprite-animated.js", + "module": "dist/esm/sprite-animated.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/sprite-animated.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/sprite-animated.js" + } + } + }, "description": "Sprite Animations as depicted by playing a series of Textures", "author": "Mat Groves", "contributors": [ @@ -20,13 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/ticker": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/sprite" + ] } diff --git a/packages/sprite-animated/src/AnimatedSprite.ts b/packages/sprite-animated/src/AnimatedSprite.ts index 68170f380b0..8038ed2ae6a 100644 --- a/packages/sprite-animated/src/AnimatedSprite.ts +++ b/packages/sprite-animated/src/AnimatedSprite.ts @@ -1,6 +1,5 @@ -import { Texture } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; -import { Ticker, UPDATE_PRIORITY } from '@pixi/ticker'; +import { Texture, Ticker, UPDATE_PRIORITY } from '@pixi/core'; import type { IDestroyOptions } from '@pixi/display'; /** @@ -31,21 +30,18 @@ import type { IDestroyOptions } from '@pixi/display'; * ... * } * ``` - * * @memberof PIXI */ export class AnimatedSprite extends Sprite { /** * The speed that the AnimatedSprite will play at. Higher is faster, lower is slower. - * * @default 1 */ public animationSpeed: number; /** * Whether or not the animate sprite repeats after playing. - * * @default true */ public loop: boolean; @@ -58,14 +54,12 @@ export class AnimatedSprite extends Sprite * of the frame (e.g. left foot). * * Note: Enabling this will override any previously set `anchor` on each frame change. - * * @default false */ public updateAnchor: boolean; /** * User-assigned function to call when an AnimatedSprite finishes playing. - * * @example * animation.onComplete = function () { * // finished! @@ -75,7 +69,6 @@ export class AnimatedSprite extends Sprite /** * User-assigned function to call when an AnimatedSprite changes which texture is being rendered. - * * @example * animation.onFrameChange = function () { * // updated! @@ -86,7 +79,6 @@ export class AnimatedSprite extends Sprite /** * User-assigned function to call when `loop` is true, and an AnimatedSprite is played and * loops around to start again. - * * @example * animation.onLoop = function () { * // looped! @@ -100,14 +92,12 @@ export class AnimatedSprite extends Sprite /** * `true` uses PIXI.Ticker.shared to auto update animation time. - * * @default true */ private _autoUpdate: boolean; /** * `true` if the instance is currently connected to PIXI.Ticker.shared to auto update animation time. - * * @default false */ private _isConnectedToTicker: boolean; @@ -123,7 +113,7 @@ export class AnimatedSprite extends Sprite * objects that make up the animation. * @param {boolean} [autoUpdate=true] - Whether to use PIXI.Ticker.shared to auto update animation time. */ - constructor(textures: Texture[]|FrameObject[], autoUpdate = true) + constructor(textures: Texture[] | FrameObject[], autoUpdate = true) { super(textures[0] instanceof Texture ? textures[0] : textures[0].texture); @@ -181,7 +171,6 @@ export class AnimatedSprite extends Sprite /** * Stops the AnimatedSprite and goes to a specific frame. - * * @param frameNumber - Frame index to stop at. */ public gotoAndStop(frameNumber: number): void @@ -200,7 +189,6 @@ export class AnimatedSprite extends Sprite /** * Goes to a specific frame and begins playing the AnimatedSprite. - * * @param frameNumber - Frame index to start at. */ public gotoAndPlay(frameNumber: number): void @@ -219,7 +207,6 @@ export class AnimatedSprite extends Sprite /** * Updates the object transform for rendering. - * * @param deltaTime - Time since last tick. */ update(deltaTime: number): void @@ -328,7 +315,6 @@ export class AnimatedSprite extends Sprite /** * Stops the AnimatedSprite and destroys it. - * * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options * have been set to that value. * @param {boolean} [options.children=false] - If set to true, all the children will have their destroy @@ -336,7 +322,7 @@ export class AnimatedSprite extends Sprite * @param {boolean} [options.texture=false] - Should it destroy the current texture of the sprite as well. * @param {boolean} [options.baseTexture=false] - Should it destroy the base texture of the sprite as well. */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { this.stop(); super.destroy(options); @@ -348,9 +334,8 @@ export class AnimatedSprite extends Sprite /** * A short hand way of creating an AnimatedSprite from an array of frame ids. - * * @param frames - The array of frames ids the AnimatedSprite will use as its texture frames. - * @return - The new animated sprite with the specified frames. + * @returns - The new animated sprite with the specified frames. */ public static fromFrames(frames: string[]): AnimatedSprite { @@ -366,9 +351,8 @@ export class AnimatedSprite extends Sprite /** * A short hand way of creating an AnimatedSprite from an array of image ids. - * * @param images - The array of image urls the AnimatedSprite will use as its texture frames. - * @return The new animate sprite with the specified images as frames. + * @returns The new animate sprite with the specified images as frames. */ public static fromImages(images: string[]): AnimatedSprite { @@ -385,7 +369,6 @@ export class AnimatedSprite extends Sprite /** * The total number of frames in the AnimatedSprite. This is the same as number of textures * assigned to the AnimatedSprite. - * * @readonly * @default 0 */ @@ -395,12 +378,12 @@ export class AnimatedSprite extends Sprite } /** The array of textures used for this AnimatedSprite. */ - get textures(): Texture[]|FrameObject[] + get textures(): Texture[] | FrameObject[] { return this._textures; } - set textures(value: Texture[]|FrameObject[]) + set textures(value: Texture[] | FrameObject[]) { if (value[0] instanceof Texture) { @@ -425,7 +408,6 @@ export class AnimatedSprite extends Sprite /** * The AnimatedSprites current frame index. - * * @readonly */ get currentFrame(): number @@ -442,7 +424,6 @@ export class AnimatedSprite extends Sprite /** * Indicates if the AnimatedSprite is currently playing. - * * @readonly */ get playing(): boolean @@ -477,7 +458,8 @@ export class AnimatedSprite extends Sprite } /** @memberof PIXI.AnimatedSprite */ -export interface FrameObject { +export interface FrameObject +{ /** The {@link PIXI.Texture} of the frame. */ texture: Texture; diff --git a/packages/sprite-animated/test/AnimatedSprite.tests.ts b/packages/sprite-animated/test/AnimatedSprite.tests.ts index 02ba960e7a0..ab418e4c725 100644 --- a/packages/sprite-animated/test/AnimatedSprite.tests.ts +++ b/packages/sprite-animated/test/AnimatedSprite.tests.ts @@ -1,330 +1,357 @@ import { AnimatedSprite } from '@pixi/sprite-animated'; import { Texture } from '@pixi/core'; -import { expect } from 'chai'; -describe('AnimatedSprite', function () +describe('AnimatedSprite', () => { - describe('instance', function () + describe('instance', () => { - beforeEach(function () + let textures: Texture[]; + let sprite: AnimatedSprite; + + beforeEach(() => { - this.textures = [Texture.EMPTY]; + textures = [Texture.EMPTY]; }); - afterEach(function () + afterEach(() => { - expect(this.sprite.animationSpeed).to.be.equal(1); - expect(this.sprite.loop).to.be.true; - expect(this.sprite.onComplete).to.be.null; - expect(this.sprite.onFrameChange).to.be.null; - expect(this.sprite.onLoop).to.be.null; - expect(this.sprite.playing).to.be.false; + expect(sprite.animationSpeed).toEqual(1); + expect(sprite.loop).toBe(true); + expect(sprite.onComplete).toBeNull(); + expect(sprite.onFrameChange).toBeNull(); + expect(sprite.onLoop).toBeNull(); + expect(sprite.playing).toBe(false); - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - it('should be correct with default options', function () + it('should be correct with default options', () => { - this.sprite = new AnimatedSprite(this.textures); - expect(this.sprite._autoUpdate).to.be.true; + sprite = new AnimatedSprite(textures); + expect(sprite['_autoUpdate']).toBe(true); }); - it('should be correct with autoUpdate=false', function () + it('should be correct with autoUpdate=false', () => { - this.sprite = new AnimatedSprite(this.textures, false); - expect(this.sprite._autoUpdate).to.be.false; + sprite = new AnimatedSprite(textures, false); + expect(sprite['_autoUpdate']).toBe(false); }); - it('should be correct with autoUpdate=true but then turned off via setter', function () + it('should be correct with autoUpdate=true but then turned off via setter', () => { - this.sprite = new AnimatedSprite(this.textures, true); - expect(this.sprite._autoUpdate).to.be.true; - this.sprite.autoUpdate = false; - expect(this.sprite._autoUpdate).to.be.false; + sprite = new AnimatedSprite(textures, true); + expect(sprite['_autoUpdate']).toBe(true); + sprite.autoUpdate = false; + expect(sprite['_autoUpdate']).toBe(false); }); }); - describe('.stop()', function () + describe('.stop()', () => { - before(function () + let sprite: AnimatedSprite; + + beforeAll(() => { - this.sprite = new AnimatedSprite([Texture.EMPTY], false); + sprite = new AnimatedSprite([Texture.EMPTY], false); }); - after(function () + afterAll(() => { - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - afterEach(function () + afterEach(() => { - this.sprite.stop(); - expect(this.sprite.playing).to.be.false; + sprite.stop(); + expect(sprite.playing).toBe(false); }); - it('should stop playing if it is playing', function () + it('should stop playing if it is playing', () => { - this.sprite._playing = true; + sprite['_playing'] = true; }); - it('should do nothing if it is not playing', function () + it('should do nothing if it is not playing', () => { - this.sprite._playing = false; + sprite['_playing'] = false; }); }); - describe('.play()', function () + describe('.play()', () => { - before(function () + let sprite: AnimatedSprite; + + beforeAll(() => { - this.sprite = new AnimatedSprite([Texture.EMPTY], false); + sprite = new AnimatedSprite([Texture.EMPTY], false); }); - after(function () + afterAll(() => { - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - afterEach(function () + afterEach(() => { - this.sprite.play(); - expect(this.sprite.playing).to.be.true; + sprite.play(); + expect(sprite.playing).toBe(true); }); - it('should start playing if it is not playing', function () + it('should start playing if it is not playing', () => { - this.sprite._playing = false; + sprite['_playing'] = false; }); - it('should do nothing if it is playing', function () + it('should do nothing if it is playing', () => { - this.sprite._playing = true; + sprite['_playing'] = true; }); }); - describe('.onComplete()', function () + describe('.onComplete()', () => { - before(function () + let sprite: AnimatedSprite; + + beforeAll(() => { - this.sprite = new AnimatedSprite([Texture.WHITE, Texture.WHITE, Texture.EMPTY]); - this.sprite.animationSpeed = 0.5; - this.sprite.loop = false; + sprite = new AnimatedSprite([Texture.WHITE, Texture.WHITE, Texture.EMPTY]); + sprite.animationSpeed = 0.5; + sprite.loop = false; }); - after(function () + afterAll(() => { - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - it('should fire onComplete', function (done) + // eslint-disable-next-line func-names + it('should fire onComplete', (done) => { - this.timeout(( - this.sprite.textures.length * 1000 / 60 / this.sprite.animationSpeed) - + (1000 / 60 / this.sprite.animationSpeed * 0.9) - ); - this.sprite.onComplete = () => + jest.setTimeout(5000); + sprite.onComplete = () => { - this.sprite.onComplete = null; + sprite.onComplete = null; done(); }; - this.sprite.play(); - expect(this.sprite.playing).to.be.true; + sprite.play(); + expect(sprite.playing).toBe(true); }); - it('should the current texture be the last item in textures', function (done) + it('should the current texture be the last item in textures', (done) => { - this.sprite.play(); - this.sprite.onComplete = () => + jest.setTimeout(5000); + sprite.play(); + sprite.onComplete = () => { - expect(this.sprite.texture === this.sprite.textures[this.sprite.currentFrame]).to.be.true; - this.sprite.onComplete = null; + expect(sprite.texture === sprite.textures[sprite.currentFrame]).toBe(true); + sprite.onComplete = null; done(); }; }); }); - describe('.gotoAndPlay()', function () + describe('.gotoAndPlay()', () => { - before(function () + let sprite: AnimatedSprite; + + beforeAll(() => { - this.sprite = new AnimatedSprite([Texture.EMPTY, Texture.EMPTY, Texture.EMPTY]); - this.sprite.animationSpeed = 0.5; - this.sprite.loop = false; + sprite = new AnimatedSprite([Texture.EMPTY, Texture.EMPTY, Texture.EMPTY]); + sprite.animationSpeed = 0.5; + sprite.loop = false; }); - after(function () + afterAll(() => { - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - it('should fire frame after start frame during one play and fire onComplete', function (done) + it('should fire frame after start frame during one play and fire onComplete', (done) => { - const frameIds = []; + jest.setTimeout(5000); + const frameIds = [] as number[]; - this.sprite.onComplete = () => + sprite.onComplete = () => { - expect(frameIds).to.deep.equal([1, 2]); - expect(this.sprite.playing).to.be.false; - this.sprite.onComplete = null; - this.sprite.onFrameChange = null; + expect(frameIds).toEqual(expect.arrayContaining([1, 2])); + expect(sprite.playing).toBe(false); + sprite.onComplete = null; + sprite.onFrameChange = null; done(); }; - this.sprite.onFrameChange = (frame) => + sprite.onFrameChange = (frame) => { frameIds.push(frame); }; - this.sprite.gotoAndPlay(1); - expect(this.sprite.playing).to.be.true; + sprite.gotoAndPlay(1); + expect(sprite.playing).toBe(true); }); }); - describe('.gotoAndStop()', function () + describe('.gotoAndStop()', () => { - before(function () + let sprite: AnimatedSprite; + + beforeAll(() => { - this.sprite = new AnimatedSprite([Texture.EMPTY, Texture.EMPTY, Texture.EMPTY]); - this.sprite.animationSpeed = 0.5; - this.sprite.loop = false; + sprite = new AnimatedSprite([Texture.EMPTY, Texture.EMPTY, Texture.EMPTY]); + sprite.animationSpeed = 0.5; + sprite.loop = false; }); - after(function () + afterAll(() => { - this.sprite.destroy(); - this.sprite = null; + sprite.destroy(); + sprite = null; }); - beforeEach(function () + beforeEach(() => { - this.sprite._playing = false; + sprite['_playing'] = false; }); - it('should fire onFrameChange on target frame', function (done) + it('should fire onFrameChange on target frame', (done) => { const targetFrame = 1; - this.sprite.onFrameChange = (frame) => + sprite.onFrameChange = (frame) => { - expect(frame).to.equal(targetFrame); - expect(this.sprite.playing).to.be.false; - this.sprite.onComplete = null; - this.sprite.onFrameChange = null; + expect(frame).toEqual(targetFrame); + expect(sprite.playing).toBe(false); + sprite.onComplete = null; + sprite.onFrameChange = null; done(); }; - this.sprite.gotoAndStop(targetFrame); - expect(this.sprite.playing).to.be.false; + sprite.gotoAndStop(targetFrame); + expect(sprite.playing).toBe(false); }); - it('should not fire onFrameChange on target frame if current is already target', function () + it('should not fire onFrameChange on target frame if current is already target', () => { let fired = false; const targetFrame = 1; - this.sprite.gotoAndStop(targetFrame); + sprite.gotoAndStop(targetFrame); - this.sprite.onFrameChange = () => + sprite.onFrameChange = () => { fired = true; }; - this.sprite.gotoAndStop(targetFrame); - expect(this.sprite.playing).to.be.false; - expect(fired).to.be.false; + sprite.gotoAndStop(targetFrame); + expect(sprite.playing).toBe(false); + expect(fired).toBe(false); }); }); - describe('.onFrameChange()', function () + describe('.onFrameChange()', () => { - before(function () - { - this.sprite = new AnimatedSprite([Texture.EMPTY, Texture.WHITE, Texture.EMPTY]); - this.sprite.animationSpeed = 0.5; - this.sprite.loop = false; - }); + let sprite: AnimatedSprite; - after(function () + beforeEach(() => { - this.sprite.destroy(); - this.sprite = null; + sprite = new AnimatedSprite([Texture.EMPTY, Texture.WHITE, Texture.EMPTY]); + sprite.animationSpeed = 0.5; + sprite.loop = false; }); - beforeEach(function () + afterEach(() => { - this.sprite._playing = false; + sprite.destroy(); + sprite = null; }); - it('should fire every frame(except current) during one play', function (done) + it('should fire every frame(except current) during one play', (done) => { - const frameIds = []; + jest.setTimeout(10000); + const frameIds = [] as number[]; - this.sprite.gotoAndStop(0); - this.sprite.onComplete = () => + sprite.gotoAndStop(0); + sprite.onComplete = () => { - expect(frameIds).to.deep.equal([1, 2]); // from 0 to 2, triggers onFrameChange at 1,2. - expect(this.sprite.currentFrame).to.equal(2); - this.sprite.onComplete = null; - this.sprite.onFrameChange = null; + expect(frameIds).toEqual(expect.arrayContaining([1, 2])); // from 0 to 2, triggers onFrameChange at 1,2. + expect(sprite.currentFrame).toEqual(2); + sprite.onComplete = null; + sprite.onFrameChange = null; done(); }; - this.sprite.onFrameChange = (frame) => + sprite.onFrameChange = (frame) => { frameIds.push(frame); }; - this.sprite.play(); - expect(this.sprite.playing).to.be.true; + sprite.autoUpdate = false; + sprite.play(); + expect(sprite.playing).toBe(true); + sprite.update(1); + sprite.update(1); + sprite.update(1); + sprite.update(1); + sprite.update(1); + sprite.update(1); }); - it('should fire every frame(except current) during one play - reverse', function (done) + it('should fire every frame(except current) during one play - reverse', (done) => { - const frameIds = []; + jest.setTimeout(10000); + const frameIds = [] as number[]; - this.sprite.gotoAndStop(2); - this.sprite.animationSpeed = -0.5; - this.sprite.onComplete = () => + sprite.gotoAndStop(2); + sprite.animationSpeed = -1; + sprite.onComplete = () => { - expect(frameIds).to.deep.equal([1, 0]); // from 2 to 0, triggers onFrameChange at 1,0. - expect(this.sprite.currentFrame).to.equal(0); - this.sprite.onComplete = null; - this.sprite.onFrameChange = null; + expect(frameIds).toEqual(expect.arrayContaining([1, 0])); // from 2 to 0, triggers onFrameChange at 1,0. + expect(sprite.currentFrame).toEqual(0); + sprite.onComplete = null; + sprite.onFrameChange = null; done(); }; - this.sprite.onFrameChange = (frame) => + sprite.onFrameChange = (frame) => { frameIds.push(frame); }; - this.sprite.play(); - expect(this.sprite.playing).to.be.true; + sprite.autoUpdate = false; + sprite.play(); + expect(sprite.playing).toBe(true); + sprite.update(1); + sprite.update(1); + sprite.update(1); }); - it('should fire every frame(except current) during one play - from not start/end', function (done) + it('should fire every frame(except current) during one play - from not start/end', (done) => { - const frameIds = []; + jest.setTimeout(10000); + const frameIds = [] as number[]; - this.sprite.gotoAndStop(1); - this.sprite.animationSpeed = -0.5; - this.sprite.onComplete = () => + sprite.gotoAndStop(1); + sprite.animationSpeed = -1; + sprite.onComplete = () => { - expect(frameIds).to.deep.equal([0]); // from 1 to 0, triggers onFrameChange at 0. - expect(this.sprite.currentFrame).to.equal(0); - this.sprite.onComplete = null; - this.sprite.onFrameChange = null; + expect(frameIds).toEqual(expect.arrayContaining([0])); // from 1 to 0, triggers onFrameChange at 0. + expect(sprite.currentFrame).toEqual(0); + sprite.onComplete = null; + sprite.onFrameChange = null; done(); }; - this.sprite.onFrameChange = (frame) => + sprite.onFrameChange = (frame) => { frameIds.push(frame); }; - this.sprite.play(); - expect(this.sprite.playing).to.be.true; + sprite.autoUpdate = false; + sprite.play(); + expect(sprite.playing).toBe(true); + sprite.update(1); + sprite.update(1); + sprite.update(1); }); }); - describe('.textures', function () + describe('.textures', () => { - it('should set the first frame when setting new textures', function (done) + it('should set the first frame when setting new textures', (done) => { const orig1 = Texture.EMPTY.clone(); const orig2 = Texture.EMPTY.clone(); @@ -344,8 +371,8 @@ describe('AnimatedSprite', function () sprite.textures = [frame1, frame2, frame3]; - expect(sprite.currentFrame).to.equal(0); - expect(sprite._texture).to.equal(frame1); + expect(sprite.currentFrame).toEqual(0); + expect(sprite._texture).toEqual(frame1); done(); }; diff --git a/packages/sprite-tiling/README.md b/packages/sprite-tiling/README.md index b652a0f4de7..06a53ef70c3 100644 --- a/packages/sprite-tiling/README.md +++ b/packages/sprite-tiling/README.md @@ -9,8 +9,5 @@ npm install @pixi/sprite-tiling ## Usage ```js -import { TilingSpriteRenderer } from '@pixi/sprite-tiling'; -import { Renderer } from '@pixi/core'; - -Renderer.registerPlugin('tilingSprite', TilingSpriteRenderer); +import '@pixi/sprite-tiling'; ``` \ No newline at end of file diff --git a/packages/sprite-tiling/package.json b/packages/sprite-tiling/package.json index cf514529401..0eab4f5f3ec 100644 --- a/packages/sprite-tiling/package.json +++ b/packages/sprite-tiling/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/sprite-tiling", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/sprite-tiling.js", - "module": "dist/esm/sprite-tiling.js", - "bundle": "dist/browser/sprite-tiling.js", + "module": "dist/esm/sprite-tiling.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/sprite-tiling.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/sprite-tiling.js" + } + } + }, "description": "Tiling Sprites for faster rendering a tiling image", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,12 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display", + "@pixi/sprite" + ] } diff --git a/packages/sprite-tiling/src/TilingSprite.ts b/packages/sprite-tiling/src/TilingSprite.ts index e39fe093777..6368723e837 100644 --- a/packages/sprite-tiling/src/TilingSprite.ts +++ b/packages/sprite-tiling/src/TilingSprite.ts @@ -1,9 +1,7 @@ -import { Texture, TextureMatrix } from '@pixi/core'; -import { Point, Rectangle, Transform } from '@pixi/math'; +import { Point, Rectangle, Transform, Texture, TextureMatrix } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; -import type { Renderer, IBaseTextureOptions, TextureSource } from '@pixi/core'; +import type { IPoint, IPointData, ISize, ObservablePoint, Renderer, IBaseTextureOptions, TextureSource } from '@pixi/core'; import type { IDestroyOptions } from '@pixi/display'; -import type { IPoint, IPointData, ISize, ObservablePoint } from '@pixi/math'; const tempPoint = new Point(); @@ -12,7 +10,6 @@ export interface TilingSprite extends GlobalMixins.TilingSprite {} /** * A tiling sprite is a fast way of rendering a tiling image. - * * @memberof PIXI */ export class TilingSprite extends Sprite @@ -29,7 +26,6 @@ export class TilingSprite extends Sprite * * This will make the texture coordinates assigned to each vertex dependent on the value of the anchor. Without * this, the top-left corner always gets the (0, 0) texture coordinate. - * * @default false */ public uvRespectAnchor: boolean; @@ -56,7 +52,6 @@ export class TilingSprite extends Sprite /** * Plugin that is responsible for rendering this element. * Allows to customize the rendering process without overriding '_render' method. - * * @default 'tilingSprite' */ this.pluginName = 'tilingSprite'; @@ -66,7 +61,6 @@ export class TilingSprite extends Sprite /** * Changes frame clamping in corresponding textureTransform, shortcut * Change to -0.5 to add a pixel to the edge, recommended for transparent trimmed textures in atlas - * * @default 0.5 * @member {number} */ @@ -87,7 +81,7 @@ export class TilingSprite extends Sprite return this.tileTransform.scale; } - set tileScale(value: ObservablePoint) + set tileScale(value: IPointData) { this.tileTransform.scale.copyFrom(value as IPoint); } @@ -117,7 +111,6 @@ export class TilingSprite extends Sprite /** * Renders the object using the WebGL renderer - * * @param renderer - The renderer */ protected _render(renderer: Renderer): void @@ -150,9 +143,8 @@ export class TilingSprite extends Sprite /** * Gets the local bounds of the sprite object. - * * @param rect - Optional output rectangle. - * @return The bounds. + * @returns The bounds. */ public getLocalBounds(rect?: Rectangle): Rectangle { @@ -182,9 +174,8 @@ export class TilingSprite extends Sprite /** * Checks if a point is inside this tiling sprite. - * * @param point - The point to check. - * @return Whether or not the sprite contains the point. + * @returns Whether or not the sprite contains the point. */ public containsPoint(point: IPointData): boolean { @@ -209,7 +200,6 @@ export class TilingSprite extends Sprite /** * Destroys this sprite and optionally its texture and children - * * @param {object|boolean} [options] - Options parameter. A boolean will act as if all options * have been set to that value * @param {boolean} [options.children=false] - if set to true, all the children will have their destroy @@ -217,7 +207,7 @@ export class TilingSprite extends Sprite * @param {boolean} [options.texture=false] - Should it destroy the current texture of the sprite as well * @param {boolean} [options.baseTexture=false] - Should it destroy the base texture of the sprite as well */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { super.destroy(options); @@ -228,15 +218,14 @@ export class TilingSprite extends Sprite /** * Helper function that creates a new tiling sprite based on the source you provide. * The source can be - frame id, image url, video url, canvas element, video element, base texture - * * @static * @param {string|PIXI.Texture|HTMLCanvasElement|HTMLVideoElement} source - Source to create texture from - * @param {Object} options - See {@link PIXI.BaseTexture}'s constructor for options. + * @param {object} options - See {@link PIXI.BaseTexture}'s constructor for options. * @param {number} options.width - required width of the tiling sprite * @param {number} options.height - required height of the tiling sprite - * @return {PIXI.TilingSprite} The newly created texture + * @returns {PIXI.TilingSprite} The newly created texture */ - static from(source: TextureSource, options: ISize & IBaseTextureOptions): TilingSprite + static from(source: TextureSource | Texture, options: ISize & IBaseTextureOptions): TilingSprite { const texture = (source instanceof Texture) ? source diff --git a/packages/sprite-tiling/src/TilingSpriteRenderer.ts b/packages/sprite-tiling/src/TilingSpriteRenderer.ts index cb208936ab2..da8bb16d188 100644 --- a/packages/sprite-tiling/src/TilingSpriteRenderer.ts +++ b/packages/sprite-tiling/src/TilingSpriteRenderer.ts @@ -1,7 +1,4 @@ -import { ObjectRenderer, Shader, State, QuadUv } from '@pixi/core'; -import { WRAP_MODES } from '@pixi/constants'; -import { Matrix } from '@pixi/math'; -import { premultiplyTintToRgba, correctBlendMode } from '@pixi/utils'; +import { ObjectRenderer, Shader, State, QuadUv, ExtensionType, WRAP_MODES, Matrix, utils } from '@pixi/core'; import fragmentSimpleSrc from './sprite-tiling-simple.frag'; import gl1VertexSrc from './sprite-tiling-fallback.vert'; @@ -9,20 +6,25 @@ import gl1FragmentSrc from './sprite-tiling-fallback.frag'; import gl2VertexSrc from './sprite-tiling.vert'; import gl2FragmentSrc from './sprite-tiling.frag'; -import type { Renderer } from '@pixi/core'; +import type { Renderer, ExtensionMetadata } from '@pixi/core'; import type { TilingSprite } from './TilingSprite'; const tempMat = new Matrix(); /** * WebGL renderer plugin for tiling sprites - * * @class * @memberof PIXI * @extends PIXI.ObjectRenderer */ export class TilingSpriteRenderer extends ObjectRenderer { + /** @ignore */ + static extension: ExtensionMetadata = { + name: 'tilingSprite', + type: ExtensionType.RendererPlugin, + }; + public shader: Shader; public simpleShader: Shader; public quad: QuadUv; @@ -30,7 +32,6 @@ export class TilingSpriteRenderer extends ObjectRenderer /** * constructor for renderer - * * @param {PIXI.Renderer} renderer - The renderer this tiling awesomeness works for. */ constructor(renderer: Renderer) @@ -44,16 +45,13 @@ export class TilingSpriteRenderer extends ObjectRenderer /** * The WebGL state in which this renderer will work. - * * @member {PIXI.State} * @readonly */ this.state = State.for2d(); } - /** - * Creates shaders when context is initialized. - */ + /** Creates shaders when context is initialized. */ contextChange(): void { const renderer = this.renderer; @@ -96,6 +94,7 @@ export class TilingSpriteRenderer extends ObjectRenderer const tex = ts._texture; const baseTex = tex.baseTexture; + const premultiplied = baseTex.alphaMode > 0; const lt = ts.tileTransform.localTransform; const uv = ts.uvMatrix; let isSimple = baseTex.isPowerOfTwo @@ -150,15 +149,15 @@ export class TilingSpriteRenderer extends ObjectRenderer } shader.uniforms.uTransform = tempMat.toArray(true); - shader.uniforms.uColor = premultiplyTintToRgba(ts.tint, ts.worldAlpha, - shader.uniforms.uColor, baseTex.alphaMode as any); + shader.uniforms.uColor = utils.premultiplyTintToRgba(ts.tint, ts.worldAlpha, + shader.uniforms.uColor, premultiplied); shader.uniforms.translationMatrix = ts.transform.worldTransform.toArray(true); shader.uniforms.uSampler = tex; renderer.shader.bind(shader); renderer.geometry.bind(quad); - this.state.blendMode = correctBlendMode(ts.blendMode, baseTex.alphaMode as any); + this.state.blendMode = utils.correctBlendMode(ts.blendMode, premultiplied); renderer.state.set(this.state); renderer.geometry.draw(this.renderer.gl.TRIANGLES, 6, 0); } diff --git a/packages/sprite-tiling/test/TilingSprite.tests.ts b/packages/sprite-tiling/test/TilingSprite.tests.ts index ccbd77e1e88..0ac7227147c 100644 --- a/packages/sprite-tiling/test/TilingSprite.tests.ts +++ b/packages/sprite-tiling/test/TilingSprite.tests.ts @@ -1,16 +1,14 @@ +import type { Bounds } from '@pixi/display'; import { Container } from '@pixi/display'; -import { Texture, BaseTexture } from '@pixi/core'; -import { Point, Rectangle } from '@pixi/math'; +import { Point, Rectangle, Texture, BaseTexture } from '@pixi/core'; import { Sprite } from '@pixi/sprite'; import { TilingSprite } from '@pixi/sprite-tiling'; -import sinon from 'sinon'; -import { expect } from 'chai'; -describe('TilingSprite', function () +describe('TilingSprite', () => { - describe('getBounds()', function () + describe('getBounds()', () => { - it('must have correct value according to _width, _height and anchor', function () + it('must have correct value according to _width, _height and anchor', () => { const parent = new Container(); const texture = new Texture(new BaseTexture()); @@ -24,16 +22,16 @@ describe('TilingSprite', function () const bounds = tilingSprite.getBounds(); - expect(bounds.x).to.equal(-150); - expect(bounds.y).to.equal(-260); - expect(bounds.width).to.equal(400); - expect(bounds.height).to.equal(600); + expect(bounds.x).toEqual(-150); + expect(bounds.y).toEqual(-260); + expect(bounds.width).toEqual(400); + expect(bounds.height).toEqual(600); }); }); - describe('.from()', function () + describe('.from()', () => { - it('should build from texture', function () + it('should build from texture', () => { const sprite = TilingSprite.from(Texture.EMPTY, { width: 1, @@ -43,7 +41,7 @@ describe('TilingSprite', function () sprite.destroy(); }); - it('should build a texture from source', function () + it('should build a texture from source', () => { const canvas = document.createElement('canvas'); @@ -59,99 +57,105 @@ describe('TilingSprite', function () }); }); - describe('.getLocalBounds()', function () + describe('.getLocalBounds()', () => { - before(function () - { - this.tileSprite = new TilingSprite(Texture.EMPTY, 1, 2); - this.tileSprite.anchor.set(3, 4); - }); + let tileSprite: TilingSprite; + let spy: jest.SpyInstance; - beforeEach(function () + beforeEach(() => { - sinon.stub(Sprite.prototype, 'getLocalBounds'); - this.tileSprite._bounds = { getRectangle: sinon.spy() }; + tileSprite = new TilingSprite(Texture.EMPTY, 1, 2); + tileSprite.anchor.set(3, 4); + spy = jest.spyOn(Sprite.prototype, 'getLocalBounds'); + spy.mockReset(); + tileSprite['_bounds'] = { getRectangle: jest.fn() } as unknown as Bounds; }); - afterEach(function () + afterEach(() => { - Sprite.prototype.getLocalBounds.restore(); + // @ts-expect-error --- + Sprite.prototype.getLocalBounds.mockClear(); }); - after(function () + afterAll(() => { - this.tileSprite.destroy(); - this.tileSprite = null; + tileSprite.destroy(); + tileSprite = null; }); - it('should call parent method if there are children', function () + it('should call parent method if there are children', () => { - this.tileSprite.children.length = 1; - this.tileSprite.getLocalBounds(); - expect(Sprite.prototype.getLocalBounds).to.be.calledOnce; - expect(this.tileSprite._bounds.getRectangle).to.not.be.called; + tileSprite.children.length = 1; + tileSprite.getLocalBounds(); + expect(Sprite.prototype.getLocalBounds).toHaveBeenCalledOnce(); + expect(tileSprite['_bounds'].getRectangle).not.toBeCalled(); }); - it('should make quick calc if no children', function () + it('should make quick calc if no children', () => { - this.tileSprite.children.length = 0; - this.tileSprite.getLocalBounds('dummy'); - - expect(this.tileSprite._bounds.getRectangle).to.be.calledOnce; - expect(this.tileSprite._bounds.getRectangle.args[0][0]).to.be.equal('dummy'); - expect(Sprite.prototype.getLocalBounds).to.not.be.called; - - expect(this.tileSprite._bounds.minX).to.be.equal(-3); - expect(this.tileSprite._bounds.minY).to.be.equal(-8); - expect(this.tileSprite._bounds.maxX).to.be.equal(-2); - expect(this.tileSprite._bounds.maxY).to.be.equal(-6); + tileSprite.children.length = 0; + // @ts-expect-error --- + tileSprite.getLocalBounds('dummy'); + + expect(tileSprite['_bounds'].getRectangle).toHaveBeenCalledOnce(); + // @ts-expect-error --- + expect(tileSprite['_bounds'].getRectangle.mock.calls[0][0]).toEqual('dummy'); + expect(Sprite.prototype.getLocalBounds).not.toBeCalled(); + + expect(tileSprite['_bounds'].minX).toEqual(-3); + expect(tileSprite['_bounds'].minY).toEqual(-8); + expect(tileSprite['_bounds'].maxX).toEqual(-2); + expect(tileSprite['_bounds'].maxY).toEqual(-6); }); - it('should assign default rect if rect is not specified', function () + it('should assign default rect if rect is not specified', () => { - this.tileSprite.children.length = 0; - this.tileSprite._localBoundsRect = 'localRect'; - this.tileSprite.getLocalBounds(); - - expect(this.tileSprite._bounds.getRectangle).to.be.calledOnce; - expect(this.tileSprite._bounds.getRectangle.args[0][0]).to.be.equal('localRect'); - expect(Sprite.prototype.getLocalBounds).to.not.be.called; - - expect(this.tileSprite._bounds.minX).to.be.equal(-3); - expect(this.tileSprite._bounds.minY).to.be.equal(-8); - expect(this.tileSprite._bounds.maxX).to.be.equal(-2); - expect(this.tileSprite._bounds.maxY).to.be.equal(-6); + tileSprite.children.length = 0; + // @ts-expect-error --- + tileSprite['_localBoundsRect'] = 'localRect'; + tileSprite.getLocalBounds(); + + expect(tileSprite['_bounds'].getRectangle).toHaveBeenCalledOnce(); + // @ts-expect-error --- + expect(tileSprite['_bounds'].getRectangle.mock.calls[0][0]).toEqual('localRect'); + expect(Sprite.prototype.getLocalBounds).not.toBeCalled(); + + expect(tileSprite['_bounds'].minX).toEqual(-3); + expect(tileSprite['_bounds'].minY).toEqual(-8); + expect(tileSprite['_bounds'].maxX).toEqual(-2); + expect(tileSprite['_bounds'].maxY).toEqual(-6); }); - it('should create and assign rect if default rect is not', function () + it('should create and assign rect if default rect is not', () => { - this.tileSprite.children.length = 0; - this.tileSprite._localBoundsRect = null; - this.tileSprite.getLocalBounds(); - - expect(this.tileSprite._bounds.getRectangle).to.be.calledOnce; - expect(this.tileSprite._bounds.getRectangle.args[0][0]).to.be.instanceof(Rectangle); - expect(Sprite.prototype.getLocalBounds).to.not.be.called; - - expect(this.tileSprite._bounds.minX).to.be.equal(-3); - expect(this.tileSprite._bounds.minY).to.be.equal(-8); - expect(this.tileSprite._bounds.maxX).to.be.equal(-2); - expect(this.tileSprite._bounds.maxY).to.be.equal(-6); + tileSprite.children.length = 0; + tileSprite['_localBoundsRect'] = null; + tileSprite.getLocalBounds(); + + expect(tileSprite['_bounds'].getRectangle).toHaveBeenCalledOnce(); + // @ts-expect-error --- + expect(tileSprite['_bounds'].getRectangle.mock.calls[0][0]).toBeInstanceOf(Rectangle); + expect(Sprite.prototype.getLocalBounds).not.toBeCalled(); + + expect(tileSprite['_bounds'].minX).toEqual(-3); + expect(tileSprite['_bounds'].minY).toEqual(-8); + expect(tileSprite['_bounds'].maxX).toEqual(-2); + expect(tileSprite['_bounds'].maxY).toEqual(-6); }); }); - it('checks if tilingSprite contains a point', function () + it('checks if tilingSprite contains a point', () => { const texture = new Texture(new BaseTexture()); const tilingSprite = new TilingSprite(texture, 200, 300); - expect(tilingSprite.containsPoint(new Point(0, 0))).to.equal(true); - expect(tilingSprite.containsPoint(new Point(10, 10))).to.equal(true); - expect(tilingSprite.containsPoint(new Point(200, 300))).to.equal(false); - expect(tilingSprite.containsPoint(new Point(300, 400))).to.equal(false); + expect(tilingSprite.containsPoint(new Point(0, 0))).toEqual(true); + expect(tilingSprite.containsPoint(new Point(10, 10))).toEqual(true); + expect(tilingSprite.containsPoint(new Point(200, 300))).toEqual(false); + expect(tilingSprite.containsPoint(new Point(300, 400))).toEqual(false); }); - it('gets and sets height and width correctly', function () + it('gets and sets height and width correctly', () => { const texture = new Texture(new BaseTexture()); const tilingSprite = new TilingSprite(texture, 200, 300); @@ -159,14 +163,14 @@ describe('TilingSprite', function () tilingSprite.width = 400; tilingSprite.height = 600; - expect(tilingSprite.width).to.equal(400); - expect(tilingSprite.height).to.equal(600); + expect(tilingSprite.width).toEqual(400); + expect(tilingSprite.height).toEqual(600); }); - it('should create TilingSprite with nullable texture', function () + it('should create TilingSprite with nullable texture', () => { const tilingSprite = new TilingSprite(null, 1, 1); - expect(tilingSprite.texture).to.equal(Texture.EMPTY); + expect(tilingSprite.texture).toEqual(Texture.EMPTY); }); }); diff --git a/packages/sprite/package.json b/packages/sprite/package.json index c7d43ed6d88..1c77db4b507 100644 --- a/packages/sprite/package.json +++ b/packages/sprite/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/sprite", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/sprite.js", - "module": "dist/esm/sprite.js", - "bundle": "dist/browser/sprite.js", + "module": "dist/esm/sprite.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/sprite.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/sprite.js" + } + } + }, "description": "Base object for textured objects rendered to the screen", "author": "Mat Groves", "contributors": [ @@ -20,16 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/display" + ] } diff --git a/packages/sprite/src/Sprite.ts b/packages/sprite/src/Sprite.ts index d514f1e54a3..886688e7a98 100644 --- a/packages/sprite/src/Sprite.ts +++ b/packages/sprite/src/Sprite.ts @@ -1,24 +1,19 @@ -import { BLEND_MODES } from '@pixi/constants'; -import { Texture } from '@pixi/core'; import { Bounds, Container } from '@pixi/display'; -import { ObservablePoint, Point, Rectangle } from '@pixi/math'; -import { settings } from '@pixi/settings'; -import { sign } from '@pixi/utils'; +import { BLEND_MODES, Texture, settings, utils, ObservablePoint, Point, Rectangle } from '@pixi/core'; -import type { IBaseTextureOptions, Renderer, TextureSource } from '@pixi/core'; +import type { IPointData, IBaseTextureOptions, Renderer, TextureSource } from '@pixi/core'; import type { IDestroyOptions } from '@pixi/display'; -import type { IPointData } from '@pixi/math'; const tempPoint = new Point(); const indices = new Uint16Array([0, 1, 2, 0, 2, 3]); -export type SpriteSource = TextureSource|Texture; +export type SpriteSource = TextureSource | Texture; export interface Sprite extends GlobalMixins.Sprite, Container {} /** * The Sprite object is the base for all textured objects that are rendered to the screen -* + * * A sprite can be created directly from an image like this: * * ```js @@ -37,14 +32,12 @@ export interface Sprite extends GlobalMixins.Sprite, Container {} * ... * } * ``` - * * @memberof PIXI */ export class Sprite extends Container { /** * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode. - * * @default PIXI.BLEND_MODES.NORMAL */ public blendMode: BLEND_MODES; @@ -53,28 +46,24 @@ export class Sprite extends Container /** * Plugin that is responsible for rendering this element. * Allows to customize the rendering process without overriding '_render' & '_renderCanvas' methods. - * * @default 'batch' */ public pluginName: string; /** * The width of the sprite (this is initially set by the texture). - * * @protected */ _width: number; /** * The height of the sprite (this is initially set by the texture) - * * @protected */ _height: number; /** * The texture that the sprite is using. - * * @private */ _texture: Texture; @@ -83,7 +72,6 @@ export class Sprite extends Container /** * Cached tint value so we can tell when the tint is changed. * Value is used for 2d CanvasRenderer. - * * @protected * @default 0xFFFFFF */ @@ -93,7 +81,6 @@ export class Sprite extends Container /** * This is used to store the uvs data of the sprite, assigned at the same time * as the vertexData in calculateVertices(). - * * @member {Float32Array} */ protected uvs: Float32Array; @@ -111,28 +98,24 @@ export class Sprite extends Container * constructing a `Sprite` does _not_ update its anchor. * * {@link https://docs.cocos2d-x.org/cocos2d-x/en/sprites/manipulation.html} - * * @default `this.texture.defaultAnchor` */ protected _anchor: ObservablePoint; /** * This is used to store the vertex data of the sprite (basically a quad). - * * @member {Float32Array} */ protected vertexData: Float32Array; /** * This is used to calculate the bounds of the object IF it is a trimmed sprite. - * * @member {Float32Array} */ private vertexTrimmedData: Float32Array; /** * Internal roundPixels field - * * @private */ private _roundPixels: boolean; @@ -141,7 +124,6 @@ export class Sprite extends Container /** * The tint applied to the sprite. This is a hex value. A value of 0xFFFFFF will remove any tint effect. - * * @default 0xFFFFFF */ private _tint: number; @@ -149,7 +131,6 @@ export class Sprite extends Container // Internal-only properties /** * The tint applied to the sprite. This is a RGB value. A value of 0xFFFFFF will remove any tint effect. - * * @private * @default 16777215 */ @@ -214,12 +195,12 @@ export class Sprite extends Container // so if _width is 0 then width was not set.. if (this._width) { - this.scale.x = sign(this.scale.x) * this._width / this._texture.orig.width; + this.scale.x = utils.sign(this.scale.x) * this._width / this._texture.orig.width; } if (this._height) { - this.scale.y = sign(this.scale.y) * this._height / this._texture.orig.height; + this.scale.y = utils.sign(this.scale.y) * this._height / this._texture.orig.height; } } @@ -374,7 +355,6 @@ export class Sprite extends Container /** * * Renders the object using the WebGL renderer - * * @param renderer - The webgl renderer to use. */ protected _render(renderer: Renderer): void @@ -408,9 +388,8 @@ export class Sprite extends Container /** * Gets the local bounds of the sprite object. - * * @param rect - Optional output rectangle. - * @return The bounds. + * @returns The bounds. */ public getLocalBounds(rect?: Rectangle): Rectangle { @@ -445,9 +424,8 @@ export class Sprite extends Container /** * Tests if a point is inside this sprite - * * @param point - the point to test - * @return The result of the test + * @returns The result of the test */ public containsPoint(point: IPointData): boolean { @@ -473,7 +451,6 @@ export class Sprite extends Container /** * Destroys this sprite and optionally its texture and children. - * * @param options - Options parameter. A boolean will act as if all options * have been set to that value * @param [options.children=false] - if set to true, all the children will have their destroy @@ -481,7 +458,7 @@ export class Sprite extends Container * @param [options.texture=false] - Should it destroy the current texture of the sprite as well * @param [options.baseTexture=false] - Should it destroy the base texture of the sprite as well */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { super.destroy(options); @@ -489,11 +466,11 @@ export class Sprite extends Container this._anchor = null; - const destroyTexture = typeof options === 'boolean' ? options : options && options.texture; + const destroyTexture = typeof options === 'boolean' ? options : options?.texture; if (destroyTexture) { - const destroyBaseTexture = typeof options === 'boolean' ? options : options && options.baseTexture; + const destroyBaseTexture = typeof options === 'boolean' ? options : options?.baseTexture; this._texture.destroy(!!destroyBaseTexture); } @@ -506,10 +483,9 @@ export class Sprite extends Container /** * Helper function that creates a new sprite based on the source you provide. * The source can be - frame id, image url, video url, canvas element, video element, base texture - * * @param {string|PIXI.Texture|HTMLCanvasElement|HTMLVideoElement} source - Source to create texture from * @param {object} [options] - See {@link PIXI.BaseTexture}'s constructor for options. - * @return The newly created sprite + * @returns The newly created sprite */ static from(source: SpriteSource, options?: IBaseTextureOptions): Sprite { @@ -527,7 +503,6 @@ export class Sprite extends Container * The main disadvantage is movement of objects may appear less smooth. * * To set the global default, change {@link PIXI.settings.ROUND_PIXELS}. - * * @default false */ set roundPixels(value: boolean) @@ -552,7 +527,7 @@ export class Sprite extends Container set width(value: number) { - const s = sign(this.scale.x) || 1; + const s = utils.sign(this.scale.x) || 1; this.scale.x = s * value / this._texture.orig.width; this._width = value; @@ -566,7 +541,7 @@ export class Sprite extends Container set height(value: number) { - const s = sign(this.scale.y) || 1; + const s = utils.sign(this.scale.y) || 1; this.scale.y = s * value / this._texture.orig.height; this._height = value; @@ -583,7 +558,6 @@ export class Sprite extends Container * Setting the anchor to `(1,1)` would mean the sprite's origin point will be the bottom right corner. * * If you pass only single parameter, it will set both x and y to the same value as shown in the example below. - * * @example * const sprite = new PIXI.Sprite(texture); * sprite.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5). @@ -602,7 +576,6 @@ export class Sprite extends Container * The tint applied to the sprite. This is a hex value. * * A value of 0xFFFFFF will remove any tint effect. - * * @default 0xFFFFFF */ get tint(): number diff --git a/packages/sprite/test/Sprite.tests.ts b/packages/sprite/test/Sprite.tests.ts index 1e899224577..7e32acf78f2 100755 --- a/packages/sprite/test/Sprite.tests.ts +++ b/packages/sprite/test/Sprite.tests.ts @@ -1,26 +1,24 @@ import { Sprite } from '@pixi/sprite'; -import { Texture, BaseTexture, RenderTexture } from '@pixi/core'; +import { Point, Texture, BaseTexture, RenderTexture } from '@pixi/core'; import { Container } from '@pixi/display'; -import { Point } from '@pixi/math'; -import { expect } from 'chai'; import path from 'path'; -describe('Sprite', function () +describe('Sprite', () => { - describe('width', function () + describe('width', () => { - it('should not be negative for negative scale.x', function () + it('should not be negative for negative scale.x', () => { const sprite = new Sprite(); sprite.width = 100; - expect(sprite.width).to.be.at.least(0); + expect(sprite.width).toBeGreaterThanOrEqual(0); sprite.scale.x = -1; - expect(sprite.width).to.be.at.least(0); + expect(sprite.width).toBeGreaterThanOrEqual(0); }); - it('should not change sign of scale.x', function () + it('should not change sign of scale.x', () => { const texture = new Texture(new BaseTexture()); const sprite = new Sprite(); @@ -29,28 +27,28 @@ describe('Sprite', function () sprite.scale.x = 1; sprite.width = 50; - expect(sprite.scale.x).to.be.above(0); + expect(sprite.scale.x).toBeGreaterThan(0); sprite.scale.x = -1; sprite.width = 75; - expect(sprite.scale.x).to.be.below(0); + expect(sprite.scale.x).toBeLessThan(0); }); }); - describe('height', function () + describe('height', () => { - it('should not be negative for negative scale.y', function () + it('should not be negative for negative scale.y', () => { const sprite = new Sprite(); sprite.height = 100; - expect(sprite.height).to.be.at.least(0); + expect(sprite.height).toBeGreaterThanOrEqual(0); sprite.scale.y = -1; - expect(sprite.height).to.be.at.least(0); + expect(sprite.height).toBeGreaterThanOrEqual(0); }); - it('should not change sign of scale.y', function () + it('should not change sign of scale.y', () => { const texture = new Texture(new BaseTexture()); const sprite = new Sprite(); @@ -59,18 +57,18 @@ describe('Sprite', function () sprite.scale.y = 1; sprite.height = 50; - expect(sprite.scale.y).to.be.above(0); + expect(sprite.scale.y).toBeGreaterThan(0); sprite.scale.y = -1; sprite.height = 75; - expect(sprite.scale.y).to.be.below(0); + expect(sprite.scale.y).toBeLessThan(0); }); }); - describe('getBounds', function () + describe('getBounds', () => { - it('must have correct value according to texture size, width, height and anchor', function () + it('must have correct value according to texture size, width, height and anchor', () => { const parent = new Container(); const texture = RenderTexture.create({ width: 20, height: 30 }); @@ -88,16 +86,16 @@ describe('Sprite', function () const bounds = sprite.getBounds(); - expect(bounds.x).to.equal(-150); - expect(bounds.y).to.equal(-260); - expect(bounds.width).to.equal(400); - expect(bounds.height).to.equal(600); + expect(bounds.x).toEqual(-150); + expect(bounds.y).toEqual(-260); + expect(bounds.width).toEqual(400); + expect(bounds.height).toEqual(600); }); }); - describe('getLocalBounds', function () + describe('getLocalBounds', () => { - it('must have correct value according to texture size, width, height and anchor', function () + it('must have correct value according to texture size, width, height and anchor', () => { const texture = RenderTexture.create({ width: 20, height: 30 }); const sprite = new Sprite(texture); @@ -106,13 +104,13 @@ describe('Sprite', function () const bounds = sprite.getLocalBounds(); - expect(bounds.x).to.equal(-10); - expect(bounds.y).to.equal(-15); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(30); + expect(bounds.x).toEqual(-10); + expect(bounds.y).toEqual(-15); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(30); }); - it('should not corrupt bounds', function () + it('should not corrupt bounds', () => { const texture = RenderTexture.create({ width: 20, height: 30 }); const sprite = new Sprite(texture); @@ -122,77 +120,82 @@ describe('Sprite', function () let bounds = sprite.getBounds(false); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(-5); - expect(bounds.width).to.equal(40); - expect(bounds.height).to.equal(30); + expect(Math.abs(bounds.x)).toEqual(0); + expect(bounds.y).toEqual(-5); + expect(bounds.width).toEqual(40); + expect(bounds.height).toEqual(30); bounds = sprite.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(30); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(30); bounds = sprite.getBounds(true); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(-5); - expect(bounds.width).to.equal(40); - expect(bounds.height).to.equal(30); + expect(Math.abs(bounds.x)).toEqual(0); + expect(bounds.y).toEqual(-5); + expect(bounds.width).toEqual(40); + expect(bounds.height).toEqual(30); }); }); - describe('containsPoint', function () + describe('containsPoint', () => { const texture = RenderTexture.create({ width: 20, height: 30 }); const sprite = new Sprite(texture); - it('should return true when point inside', function () + it('should return true when point inside', () => { const point = new Point(10, 10); - expect(sprite.containsPoint(point)).to.be.true; + expect(sprite.containsPoint(point)).toBe(true); }); - it('should return true when point on left edge', function () + it('should return true when point on left edge', () => { const point = new Point(0, 15); - expect(sprite.containsPoint(point)).to.be.true; + expect(sprite.containsPoint(point)).toBe(true); }); - it('should return true when point on top edge', function () + it('should return true when point on top edge', () => { const point = new Point(10, 0); - expect(sprite.containsPoint(point)).to.be.true; + expect(sprite.containsPoint(point)).toBe(true); }); - it('should return false when point outside', function () + it('should return false when point outside', () => { const point = new Point(100, 100); - expect(sprite.containsPoint(point)).to.be.false; + expect(sprite.containsPoint(point)).toBe(false); }); }); - describe('texture', function () + interface EETexture extends Texture { - it('should unsubscribe from old texture', function () + _eventsCount: number; // missing in ee3 typings + } + + describe('texture', () => + { + it('should unsubscribe from old texture', () => { - const texture = new Texture(new BaseTexture()); - const texture2 = new Texture(new BaseTexture()); + const texture = new Texture(new BaseTexture()) as EETexture; + const texture2 = new Texture(new BaseTexture()) as EETexture; const sprite = new Sprite(texture); - expect(texture._eventsCount).to.equal(1); - expect(texture2._eventsCount).to.equal(0); + expect(texture['_eventsCount']).toEqual(1); + expect(texture2['_eventsCount']).toEqual(0); sprite.texture = texture2; - expect(texture._eventsCount).to.equal(0); - expect(texture2._eventsCount).to.equal(1); + expect(texture['_eventsCount']).toEqual(0); + expect(texture2['_eventsCount']).toEqual(1); sprite.destroy(); texture.destroy(true); @@ -200,18 +203,18 @@ describe('Sprite', function () }); }); - describe('destroy', function () + describe('destroy', () => { - it('should destroy while BaseTexture is loading', function () + it('should destroy while BaseTexture is loading', () => { - const texture = Texture.from(path.resolve(__dirname, 'resources', 'building1.png')); + const texture = Texture.from(path.resolve(__dirname, 'resources', 'building1.png')) as EETexture; const sprite = new Sprite(texture); - expect(texture._eventsCount).to.equal(1); + expect(texture['_eventsCount']).toEqual(1); sprite.destroy(); - expect(texture._eventsCount).to.equal(0); + expect(texture['_eventsCount']).toEqual(0); texture.emit('update', texture); texture.destroy(true); diff --git a/packages/spritesheet/README.md b/packages/spritesheet/README.md index 7c26b10797f..29d4561a50f 100644 --- a/packages/spritesheet/README.md +++ b/packages/spritesheet/README.md @@ -9,7 +9,5 @@ npm install @pixi/spritesheet ## Usage ```js -import { SpritesheetLoader } from '@pixi/spritesheet'; -import { Loader } from '@pixi/loaders'; -Loader.registerPlugin(SpritesheetLoader); +import '@pixi/spritesheet'; ``` \ No newline at end of file diff --git a/packages/spritesheet/package.json b/packages/spritesheet/package.json index 2bb0bbc1c1c..40fe35cceba 100644 --- a/packages/spritesheet/package.json +++ b/packages/spritesheet/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/spritesheet", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/spritesheet.js", - "module": "dist/esm/spritesheet.js", - "bundle": "dist/browser/spritesheet.js", + "module": "dist/esm/spritesheet.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/spritesheet.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/spritesheet.js" + } + } + }, "description": "Spritesheets maintain a collection of Textures on a single image", "author": "Mat Groves", "contributors": [ @@ -20,14 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/loaders": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/assets", + "@pixi/core" + ] } diff --git a/packages/spritesheet/src/Spritesheet.ts b/packages/spritesheet/src/Spritesheet.ts index 7b324f3763e..860dd7f7d38 100644 --- a/packages/spritesheet/src/Spritesheet.ts +++ b/packages/spritesheet/src/Spritesheet.ts @@ -1,14 +1,9 @@ -import { Rectangle } from '@pixi/math'; -import { Texture, BaseTexture } from '@pixi/core'; -import { getResolutionOfUrl } from '@pixi/utils'; -import type { Dict } from '@pixi/utils'; -import type { ImageResource } from '@pixi/core'; -import type { IPointData } from '@pixi/math'; +import { Texture, BaseTexture, utils, Rectangle } from '@pixi/core'; +import type { ImageResource, IPointData } from '@pixi/core'; -/** - * Represents the JSON data for a spritesheet atlas. - */ -export interface ISpritesheetFrameData { +/** Represents the JSON data for a spritesheet atlas. */ +export interface ISpritesheetFrameData +{ frame: { x: number; y: number; @@ -28,14 +23,15 @@ export interface ISpritesheetFrameData { anchor?: IPointData; } -/** - * Atlas format. - */ -export interface ISpritesheetData { - frames: Dict; - animations?: Dict; +/** Atlas format. */ +export interface ISpritesheetData +{ + frames: utils.Dict; + animations?: utils.Dict; meta: { scale: string; + // eslint-disable-next-line camelcase + related_multi_packs?: string[]; }; } @@ -43,7 +39,7 @@ export interface ISpritesheetData { * Utility class for maintaining reference to a collection * of Textures on a single Spritesheet. * - * To access a sprite sheet from your code pass its JSON data file to Pixi's loader: + * To access a sprite sheet from your code you may pass its JSON data file to Pixi's loader: * * ```js * PIXI.Loader.shared.add("images/spritesheet.json").load(setup); @@ -53,13 +49,20 @@ export interface ISpritesheetData { * ... * } * ``` + * + * Alternately, you may circumvent the loader by instantiating the Spritesheet directly: + * ```js + * const sheet = new PIXI.Spritesheet(texture, spritesheetData); + * await sheet.parse(); + * console.log('Spritesheet ready to use!'); + * ``` + * * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite. * * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker}, * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}. * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only * supported by TexturePacker. - * * @memberof PIXI */ export class Spritesheet @@ -67,6 +70,9 @@ export class Spritesheet /** The maximum number of Textures to build per process. */ static readonly BATCH_SIZE = 1000; + /** For multi-packed spritesheets, this contains a reference to all the other spritesheets it depends on. */ + public linkedSheets: Spritesheet[] = []; + /** Reference to ths source texture. */ public baseTexture: BaseTexture; @@ -77,7 +83,7 @@ export class Spritesheet * new PIXI.Sprite(sheet.textures["image.png"]); * ``` */ - public textures: Dict; + public textures: utils.Dict; /** * A map containing the textures for each animation. @@ -86,11 +92,11 @@ export class Spritesheet * new PIXI.AnimatedSprite(sheet.animations["anim_name"]) * ``` */ - public animations: Dict; + public animations: utils.Dict; /** * Reference to the original JSON data. - * @type {Object} + * @type {object} */ public data: ISpritesheetData; @@ -105,9 +111,9 @@ export class Spritesheet /** * Map of spritesheet frames. - * @type {Object} + * @type {object} */ - private _frames: Dict; + private _frames: utils.Dict; /** Collection of frame names. */ private _frameKeys: string[]; @@ -119,11 +125,11 @@ export class Spritesheet * Callback when parse is completed. * @type {Function} */ - private _callback: (textures: Dict) => void; + private _callback: (textures: utils.Dict) => void; /** - * @param baseTexture - Reference to the source BaseTexture object. - * @param {Object} data - Spritesheet image data. + * @param texture - Reference to the source BaseTexture object. + * @param {object} data - Spritesheet image data. * @param resolutionFilename - The filename to consider when determining * the resolution of the spritesheet. If not provided, the imageUrl will * be used on the BaseTexture. @@ -148,23 +154,22 @@ export class Spritesheet /** * Generate the resolution from the filename or fallback * to the meta.scale field of the JSON data. - * * @param resolutionFilename - The filename to use for resolving * the default resolution. - * @return Resolution to use for spritesheet. + * @returns Resolution to use for spritesheet. */ private _updateResolution(resolutionFilename: string = null): number { const { scale } = this.data.meta; // Use a defaultValue of `null` to check if a url-based resolution is set - let resolution = getResolutionOfUrl(resolutionFilename, null); + let resolution = utils.getResolutionOfUrl(resolutionFilename, null); // No resolution found via URL if (resolution === null) { // Use the scale value or default to 1 - resolution = scale !== undefined ? parseFloat(scale) : 1; + resolution = parseFloat(scale ?? '1'); } // For non-1 resolutions, update baseTexture @@ -179,30 +184,30 @@ export class Spritesheet /** * Parser spritesheet from loaded data. This is done asynchronously * to prevent creating too many Texture within a single process. - * - * @param {Function} callback - Callback when complete returns - * a map of the Textures for this spritesheet. + * @method PIXI.Spritesheet#parse */ - public parse(callback: (textures?: Dict) => void): void + public parse(): Promise> { - this._batchIndex = 0; - this._callback = callback; - - if (this._frameKeys.length <= Spritesheet.BATCH_SIZE) - { - this._processFrames(0); - this._processAnimations(); - this._parseComplete(); - } - else + return new Promise((resolve) => { - this._nextBatch(); - } + this._callback = resolve; + this._batchIndex = 0; + + if (this._frameKeys.length <= Spritesheet.BATCH_SIZE) + { + this._processFrames(0); + this._processAnimations(); + this._parseComplete(); + } + else + { + this._nextBatch(); + } + }); } /** * Process a batch of frames - * * @param initialFrameIndex - The index of frame to start. */ private _processFrames(initialFrameIndex: number): void @@ -325,7 +330,6 @@ export class Spritesheet /** * Destroy Spritesheet and don't use after this. - * * @param {boolean} [destroyBase=false] - Whether to destroy the base texture as well */ public destroy(destroyBase = false): void @@ -345,19 +349,6 @@ export class Spritesheet } this._texture = null; this.baseTexture = null; + this.linkedSheets = []; } } - -/** - * Reference to Spritesheet object created. - * @member {PIXI.Spritesheet} spritesheet - * @memberof PIXI.LoaderResource - * @instance - */ - -/** - * Dictionary of textures from Spritesheet. - * @member {object} textures - * @memberof PIXI.LoaderResource - * @instance - */ diff --git a/packages/spritesheet/src/SpritesheetLoader.ts b/packages/spritesheet/src/SpritesheetLoader.ts deleted file mode 100644 index 62587c45f8f..00000000000 --- a/packages/spritesheet/src/SpritesheetLoader.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { url } from '@pixi/utils'; -import { Spritesheet } from './Spritesheet'; -import { LoaderResource } from '@pixi/loaders'; -import type { Loader } from '@pixi/loaders'; - -/** - * {@link PIXI.Loader} middleware for loading texture atlases that have been created with - * TexturePacker or similar JSON-based spritesheet. - * - * This middleware automatically generates Texture resources. - * - * If you're using Webpack or other bundlers and plan on bundling the atlas' JSON, - * use the {@link PIXI.Spritesheet} class to directly parse the JSON. - * - * The Loader's image Resource name is automatically appended with `"_image"`. - * If a Resource with this name is already loaded, the Loader will skip parsing the - * Spritesheet. The code below will generate an internal Loader Resource called `"myatlas_image"`. - * - * @example - * loader.add('myatlas', 'path/to/myatlas.json'); - * loader.load(() => { - * loader.resources.myatlas; // atlas JSON resource - * loader.resources.myatlas_image; // atlas Image resource - * }); - * - * @memberof PIXI - */ -export class SpritesheetLoader -{ - /** - * Called after a resource is loaded. - * - * @see PIXI.Loader.loaderMiddleware - * @param resource - * @param next - */ - static use(resource: LoaderResource, next: (...args: unknown[]) => void): void - { - // because this is middleware, it execute in loader context. `this` = loader - const loader = (this as any) as Loader; - const imageResourceName = `${resource.name}_image`; - - // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data - || resource.type !== LoaderResource.TYPE.JSON - || !resource.data.frames - || loader.resources[imageResourceName] - ) - { - next(); - - return; - } - - // Check and add the multi atlas - // Heavily influenced and based on https://github.com/rocket-ua/pixi-tps-loader/blob/master/src/ResourceLoader.js - // eslint-disable-next-line camelcase - const multiPacks = resource.data?.meta?.related_multi_packs; - - if (Array.isArray(multiPacks)) - { - for (const item of multiPacks) - { - if (typeof item !== 'string') - { - continue; - } - - const itemName = item.replace('.json', ''); - const itemUrl = url.resolve(resource.url.replace(loader.baseUrl, ''), item); - - // Check if the file wasn't already added as multipacks are redundant - if (loader.resources[itemName] - || Object.values(loader.resources).some((r) => url.format(url.parse(r.url)) === itemUrl)) - { - continue; - } - - const options = { - crossOrigin: resource.crossOrigin, - loadType: LoaderResource.LOAD_TYPE.XHR, - xhrType: LoaderResource.XHR_RESPONSE_TYPE.JSON, - parentResource: resource, - metadata: resource.metadata - }; - - loader.add(itemName, itemUrl, options); - } - } - - const loadOptions = { - crossOrigin: resource.crossOrigin, - metadata: resource.metadata.imageMetadata, - parentResource: resource, - }; - - const resourcePath = SpritesheetLoader.getResourcePath(resource, loader.baseUrl); - - // load the image for this sheet - loader.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res: LoaderResource) - { - if (res.error) - { - next(res.error); - - return; - } - - const spritesheet = new Spritesheet( - res.texture, - resource.data, - resource.url - ); - - spritesheet.parse(() => - { - resource.spritesheet = spritesheet; - resource.textures = spritesheet.textures; - next(); - }); - }); - } - - /** - * Get the spritesheets root path - * - * @param resource - Resource to check path - * @param baseUrl - Base root url - */ - static getResourcePath(resource: LoaderResource, baseUrl: string): string - { - // Prepend url path unless the resource image is a data url - if (resource.isDataUrl) - { - return resource.data.meta.image; - } - - return url.resolve(resource.url.replace(baseUrl, ''), resource.data.meta.image); - } -} diff --git a/packages/spritesheet/src/cacheSpritesheet.ts b/packages/spritesheet/src/cacheSpritesheet.ts new file mode 100644 index 00000000000..995ba3caf15 --- /dev/null +++ b/packages/spritesheet/src/cacheSpritesheet.ts @@ -0,0 +1,40 @@ +import { extensions, ExtensionType, utils } from '@pixi/core'; +import { Spritesheet } from './Spritesheet'; +import type { CacheParser } from '@pixi/assets'; + +function getCacheableAssets(keys: string[], asset: Spritesheet, ignoreMultiPack: boolean) +{ + const out: Record = {}; + + keys.forEach((key: string) => + { + out[key] = asset; + }); + + Object.keys(asset.textures).forEach((key) => + { + out[key] = asset.textures[key]; + }); + + if (!ignoreMultiPack) + { + const basePath = utils.path.dirname(keys[0]); + + asset.linkedSheets.forEach((item: Spritesheet, i) => + { + const out2 = getCacheableAssets([`${basePath}/${asset.data.meta.related_multi_packs[i]}`], item, true); + + Object.assign(out, out2); + }); + } + + return out; +} + +export const cacheSpritesheet: CacheParser = { + extension: ExtensionType.CacheParser, + test: (asset: Spritesheet) => asset instanceof Spritesheet, + getCacheableAssets: (keys: string[], asset: Spritesheet) => getCacheableAssets(keys, asset, false) +}; + +extensions.add(cacheSpritesheet); diff --git a/packages/spritesheet/src/index.ts b/packages/spritesheet/src/index.ts index 7b35ca904f2..ca0030dfe01 100644 --- a/packages/spritesheet/src/index.ts +++ b/packages/spritesheet/src/index.ts @@ -1,2 +1,4 @@ +export * from './loadSpritesheet'; export * from './Spritesheet'; -export * from './SpritesheetLoader'; +export * from './cacheSpritesheet'; +export * from './resolveSpriteSheetUrl'; diff --git a/packages/spritesheet/src/loadSpritesheet.ts b/packages/spritesheet/src/loadSpritesheet.ts new file mode 100644 index 00000000000..a9f04c09f45 --- /dev/null +++ b/packages/spritesheet/src/loadSpritesheet.ts @@ -0,0 +1,109 @@ +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; +import { LoaderParserPriority } from '@pixi/assets'; +import type { Texture } from '@pixi/core'; +import { extensions, ExtensionType, utils } from '@pixi/core'; +import type { ISpritesheetData } from './Spritesheet'; +import { Spritesheet } from './Spritesheet'; + +interface SpriteSheetJson extends ISpritesheetData +{ + meta: { + image: string; + scale: string; + // eslint-disable-next-line camelcase + related_multi_packs?: string[]; + }; +} + +/** + * Loader plugin that parses sprite sheets! + * once the JSON has been loaded this checks to see if the JSON is spritesheet data. + * If it is, we load the spritesheets image and parse the data into PIXI.Spritesheet + * All textures in the sprite sheet are then added to the cache + */ +export const loadSpritesheet = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.Normal, + }, + + async testParse(asset: SpriteSheetJson, options: LoadAsset): Promise + { + return (utils.path.extname(options.src).includes('.json') && !!asset.frames); + }, + + async parse(asset: SpriteSheetJson, options: LoadAsset, loader: Loader): Promise + { + let basePath = utils.path.dirname(options.src); + + if (basePath && basePath.lastIndexOf('/') !== (basePath.length - 1)) + { + basePath += '/'; + } + + const imagePath = basePath + asset.meta.image; + + const assets = await loader.load([imagePath]) as Record; + + const texture = assets[imagePath]; + + const spritesheet = new Spritesheet( + texture.baseTexture, + asset, + options.src, + ); + + await spritesheet.parse(); + + // Check and add the multi atlas + // Heavily influenced and based on https://github.com/rocket-ua/pixi-tps-loader/blob/master/src/ResourceLoader.js + // eslint-disable-next-line camelcase + const multiPacks = asset?.meta?.related_multi_packs; + + if (Array.isArray(multiPacks)) + { + const promises: Promise[] = []; + + for (const item of multiPacks) + { + if (typeof item !== 'string') + { + continue; + } + + const itemUrl = basePath + item; + + // Check if the file wasn't already added as multipack + if (options.data?.ignoreMultiPack) + { + continue; + } + + promises.push(loader.load({ + src: itemUrl, + data: { + ignoreMultiPack: true, + } + })); + } + + const res = await Promise.all(promises); + + spritesheet.linkedSheets = res; + res.forEach((item) => + { + item.linkedSheets = [spritesheet].concat(spritesheet.linkedSheets.filter((sp) => (sp !== item))); + }); + } + + return spritesheet; + }, + + unload(spritesheet: Spritesheet) + { + spritesheet.destroy(true); + }, + +} as LoaderParser; + +extensions.add(loadSpritesheet); diff --git a/packages/spritesheet/src/resolveSpriteSheetUrl.ts b/packages/spritesheet/src/resolveSpriteSheetUrl.ts new file mode 100644 index 00000000000..576c27cd074 --- /dev/null +++ b/packages/spritesheet/src/resolveSpriteSheetUrl.ts @@ -0,0 +1,32 @@ +import { settings, extensions, ExtensionType } from '@pixi/core'; +import type { ResolveAsset, ResolveURLParser } from '@pixi/assets'; + +const validImages = ['jpg', 'png', 'jpeg', 'avif', 'webp']; + +export const resolveSpriteSheetUrl = { + extension: ExtensionType.ResolveParser, + + test: (value: string): boolean => + { + const tempURL = value.split('?')[0]; + + const split = tempURL.split('.'); + + const extension = split.pop(); + const format = split.pop(); + + return extension === 'json' && validImages.includes(format); + }, + parse: (value: string): ResolveAsset => + { + const split = value.split('.'); + + return { + resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'), + format: split[split.length - 2], + src: value, + }; + }, +} as ResolveURLParser; + +extensions.add(resolveSpriteSheetUrl); diff --git a/packages/spritesheet/test/Spritesheet.tests.ts b/packages/spritesheet/test/Spritesheet.tests.ts index d19c84a1aae..22435040d91 100644 --- a/packages/spritesheet/test/Spritesheet.tests.ts +++ b/packages/spritesheet/test/Spritesheet.tests.ts @@ -1,61 +1,67 @@ +import type { ISpritesheetData, ISpritesheetFrameData } from '@pixi/spritesheet'; import { Spritesheet } from '@pixi/spritesheet'; +import type { ImageResource } from '@pixi/core'; import { BaseTexture, Texture } from '@pixi/core'; import path from 'path'; -import { expect } from 'chai'; -describe('Spritesheet', function () +describe('Spritesheet', () => { - before(function () + let resources: string; + let validate: (spritesheet: Spritesheet, done: () => void) => void; + let parseFrame: (frameData: ISpritesheetFrameData, cb: (frame: Texture) => void) => void; + + beforeAll(() => { - this.resources = path.join(__dirname, 'resources'); - this.validate = function (spritesheet, done) + resources = path.join(__dirname, 'resources'); + validate = (spritesheet: Spritesheet, done) => { - spritesheet.parse(function (textures) + spritesheet.parse().then((textures) => { const id = 'goldmine_10_5.png'; const width = Math.floor(spritesheet.data.frames[id].frame.w); const height = Math.floor(spritesheet.data.frames[id].frame.h); - expect(Object.keys(textures).length).to.equal(5); - expect(Object.keys(spritesheet.textures).length).to.equal(5); - expect(textures[id]).to.be.an.instanceof(Texture); - expect(textures[id].width).to.equal(width / spritesheet.resolution); - expect(textures[id].height).to.equal(height / spritesheet.resolution); - expect(textures[id].defaultAnchor.x).to.equal(0); - expect(textures[id].defaultAnchor.y).to.equal(0); - expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0); + expect(Object.keys(textures).length).toEqual(5); + expect(Object.keys(spritesheet.textures).length).toEqual(5); + expect(textures[id]).toBeInstanceOf(Texture); + expect(textures[id].width).toEqual(width / spritesheet.resolution); + expect(textures[id].height).toEqual(height / spritesheet.resolution); + expect(textures[id].defaultAnchor.x).toEqual(0); + expect(textures[id].defaultAnchor.y).toEqual(0); + expect(textures[id].textureCacheIds.indexOf(id)).toEqual(0); - expect(this.animations).to.have.property('star').that.is.an('array'); - expect(this.animations.star.length).to.equal(4); - expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5); - expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5); + expect(spritesheet.animations.star).toBeArray(); + expect(spritesheet.animations.star.length).toEqual(4); + expect(spritesheet.animations.star[0].defaultAnchor.x).toEqual(0.5); + expect(spritesheet.animations.star[0].defaultAnchor.y).toEqual(0.5); spritesheet.destroy(true); - expect(spritesheet.textures).to.be.null; - expect(spritesheet.baseTexture).to.be.null; + expect(spritesheet.textures).toBeNull(); + expect(spritesheet.baseTexture).toBeNull(); done(); }); }; - this.parseFrame = function (frameData, callback) + parseFrame = (frameData, callback) => { const data = { frames: { frame: frameData }, meta: { scale: 1 }, - }; + } as unknown as ISpritesheetData; const baseTexture = BaseTexture.from( document.createElement('canvas') - ); + ) as BaseTexture; + // @ts-expect-error - hack baseTexture.imageUrl = 'test.png'; const sheet = new Spritesheet(baseTexture, data); - sheet.parse(() => + sheet.parse().then(() => { const { frame } = sheet.textures; - expect(frame).to.be.instanceof(Texture); + expect(frame).toBeInstanceOf(Texture); callback(frame); @@ -64,81 +70,85 @@ describe('Spritesheet', function () }; }); - it('should exist on PIXI', function () + it('should exist on PIXI', () => { - expect(Spritesheet).to.be.a('function'); - expect(Spritesheet.BATCH_SIZE).to.be.a('number'); + expect(Spritesheet).toBeInstanceOf(Function); + expect(Spritesheet.BATCH_SIZE).toBeNumber(); }); - it('should create an instance', function () + it('should create an instance', () => { const baseTexture = new BaseTexture(); const data = { frames: {}, meta: {}, - }; + } as unknown as ISpritesheetData; const spritesheet = new Spritesheet(baseTexture, data); - expect(spritesheet.data).to.equal(data); - expect(spritesheet.baseTexture).to.equal(baseTexture); - expect(spritesheet.resolution).to.equal(1); + expect(spritesheet.data).toEqual(data); + expect(spritesheet.baseTexture).toEqual(baseTexture); + expect(spritesheet.resolution).toEqual(1); spritesheet.destroy(true); }); - it('should create instance with scale resolution', function (done) + it('should create instance with scale resolution', (done) => { - const data = require(path.resolve(this.resources, 'building1.json')); // eslint-disable-line global-require + jest.setTimeout(10000); + // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require + const data = require(path.resolve(resources, 'building1.json')); const image = new Image(); - image.src = path.join(this.resources, data.meta.image); + image.src = path.join(resources, data.meta.image); image.onload = () => { - const baseTexture = new BaseTexture(image, null, 1); + const baseTexture = new BaseTexture(image, null); const spritesheet = new Spritesheet(baseTexture, data); - expect(data).to.be.an('object'); - expect(data.meta.image).to.equal('building1.png'); - expect(spritesheet.resolution).to.equal(0.5); - this.validate(spritesheet, done); + expect(data).toBeObject(); + expect(data.meta.image).toEqual('building1.png'); + expect(spritesheet.resolution).toEqual(0.5); + validate(spritesheet, done); }; }); - it('should create instance with BaseTexture source scale', function (done) + it('should create instance with BaseTexture source scale', (done) => { - const data = require(path.resolve(this.resources, 'building1.json')); // eslint-disable-line global-require + // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require + const data = require(path.resolve(resources, 'building1.json')); const baseTexture = BaseTexture.from(data.meta.image);// , undefined, undefined, 1.5); const spritesheet = new Spritesheet(baseTexture, data); - expect(data).to.be.an('object'); - expect(data.meta.image).to.equal('building1.png'); - expect(spritesheet.resolution).to.equal(0.5); + expect(data).toBeObject(); + expect(data.meta.image).toEqual('building1.png'); + expect(spritesheet.resolution).toEqual(0.5); - this.validate(spritesheet, done); + validate(spritesheet, done); }); - it('should create instance with filename resolution', function (done) + it('should create instance with filename resolution', (done) => { - const uri = path.resolve(this.resources, 'building1@2x.json'); - const data = require(uri); // eslint-disable-line global-require + const uri = path.resolve(resources, 'building1@2x.json'); + // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require + const data = require(uri); const image = new Image(); - image.src = path.join(this.resources, data.meta.image); + image.src = path.join(resources, data.meta.image); image.onload = () => { const baseTexture = new BaseTexture(image, { resolution: 1 }); const spritesheet = new Spritesheet(baseTexture, data, uri); - expect(data).to.be.an('object'); - expect(data.meta.image).to.equal('building1@2x.png'); - expect(spritesheet.resolution).to.equal(2); + expect(data).toBeObject(); + expect(data.meta.image).toEqual('building1@2x.png'); + expect(spritesheet.resolution).toEqual(2); - this.validate(spritesheet, done); + validate(spritesheet, done); }; }); - it('should parse full data untrimmed', function (done) + it('should parse full data untrimmed', (done) => { const data = { frame: { x: 0, y: 0, w: 14, h: 16 }, @@ -146,17 +156,17 @@ describe('Spritesheet', function () trimmed: false, spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, sourceSize: { w: 14, h: 16 }, - }; + } as ISpritesheetFrameData; - this.parseFrame(data, (texture) => + parseFrame(data, (texture) => { - expect(texture.width).to.equal(14); - expect(texture.height).to.equal(16); + expect(texture.width).toEqual(14); + expect(texture.height).toEqual(16); done(); }); }); - it('should parse texture from trimmed', function (done) + it('should parse texture from trimmed', (done) => { const data = { frame: { x: 0, y: 28, w: 14, h: 14 }, @@ -166,27 +176,27 @@ describe('Spritesheet', function () sourceSize: { w: 40, h: 20 }, }; - this.parseFrame(data, (texture) => + parseFrame(data, (texture) => { - expect(texture.width).to.equal(40); - expect(texture.height).to.equal(20); + expect(texture.width).toEqual(40); + expect(texture.height).toEqual(20); done(); }); }); - it('should parse texture from minimal data', function (done) + it('should parse texture from minimal data', (done) => { const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; - this.parseFrame(data, (texture) => + parseFrame(data, (texture) => { - expect(texture.width).to.equal(14); - expect(texture.height).to.equal(14); + expect(texture.width).toEqual(14); + expect(texture.height).toEqual(14); done(); }); }); - it('should parse texture without trimmed or sourceSize', function (done) + it('should parse texture without trimmed or sourceSize', (done) => { const data = { frame: { x: 0, y: 14, w: 14, h: 14 }, @@ -195,15 +205,15 @@ describe('Spritesheet', function () spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, }; - this.parseFrame(data, (texture) => + parseFrame(data, (texture) => { - expect(texture.width).to.equal(14); - expect(texture.height).to.equal(14); + expect(texture.width).toEqual(14); + expect(texture.height).toEqual(14); done(); }); }); - it('should parse as trimmed if spriteSourceSize is set', function (done) + it('should parse as trimmed if spriteSourceSize is set', (done) => { // shoebox format const data = { @@ -212,10 +222,10 @@ describe('Spritesheet', function () sourceSize: { w: 120, h: 100 }, }; - this.parseFrame(data, (texture) => + parseFrame(data, (texture) => { - expect(texture.width).to.equal(120); - expect(texture.height).to.equal(100); + expect(texture.width).toEqual(120); + expect(texture.height).toEqual(100); done(); }); }); diff --git a/packages/spritesheet/test/SpritesheetLoader.tests.ts b/packages/spritesheet/test/SpritesheetLoader.tests.ts index 07d74751e11..e711a7c583a 100644 --- a/packages/spritesheet/test/SpritesheetLoader.tests.ts +++ b/packages/spritesheet/test/SpritesheetLoader.tests.ts @@ -1,399 +1,149 @@ -import path from 'path'; -import { Loader, LoaderResource } from '@pixi/loaders'; -import { Texture, BaseTexture } from '@pixi/core'; -import { BaseTextureCache, TextureCache, url, clearTextureCache } from '@pixi/utils'; -import { SpritesheetLoader, Spritesheet } from '@pixi/spritesheet'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { Cache, loadJson, loadTextures } from '@pixi/assets'; +import { Texture } from '@pixi/core'; +import { cacheSpritesheet, loadSpritesheet, resolveSpriteSheetUrl, Spritesheet } from '@pixi/spritesheet'; +import { clearTextureCache } from '@pixi/utils'; +import { Loader } from '../../assets/src/loader/Loader'; -describe('SpritesheetLoader', function () +describe('SpritesheetLoader', () => { - it('should exist and return a function', function () - { - expect(SpritesheetLoader).to.not.be.undefined; - expect(SpritesheetLoader.use).to.be.a('function'); - }); - - it('should install middleware', function (done) - { - Loader.registerPlugin(SpritesheetLoader); - - const loader = new Loader(); - const baseTextures = Object.keys(BaseTextureCache).length; - const textures = Object.keys(TextureCache).length; + let loader: Loader; + const serverPath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/spritesheet/test/resources/` + : 'http://localhost:8080/spritesheet/test/resources/'; - loader.add('building1', path.join(__dirname, 'resources/building1.json')); - loader.load((loader, resources) => - { - expect(resources.building1).to.be.instanceof(LoaderResource); - expect(resources.building1.spritesheet).to.be.instanceof(Spritesheet); - resources.building1.spritesheet.destroy(true); - expect(Object.keys(BaseTextureCache).length).to.equal(baseTextures); - expect(Object.keys(TextureCache).length).to.equal(textures); - loader.reset(); - done(); - }); - }); - - it('should do nothing if the resource is not JSON', function () + beforeEach(() => { - const spy = sinon.spy(); - const res = {}; - - SpritesheetLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.textures).to.be.undefined; + Cache.reset(); + loader.reset(); }); - it('should do nothing if the resource is JSON, but improper format', function () + beforeAll(() => { - const spy = sinon.spy(); - const res = createMockResource(LoaderResource.TYPE.JSON, {}); - - SpritesheetLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.textures).to.be.undefined; + loader = new Loader(); + loader['_parsers'].push(loadJson, loadTextures, loadSpritesheet); }); - it('should load the image & create textures if json is properly formatted', function () + it('should load a spritesheet', async () => { - const spy = sinon.spy(); - const res = createMockResource(LoaderResource.TYPE.JSON, getJsonSpritesheet()); - const loader = new Loader(); - const addStub = sinon.stub(loader, 'add'); - const imgRes = createMockResource(LoaderResource.TYPE.IMAGE, new Image()); - - imgRes.texture = new Texture(new BaseTexture(imgRes.data)); - - addStub.yields(imgRes); + const spriteSheet: Spritesheet = await loader.load(`${serverPath}spritesheet.json`); - SpritesheetLoader.use.call(loader, res, spy); + const bunnyTexture = spriteSheet.textures['bunny.png']; + const senseiTexture = spriteSheet.textures['pic-sensei.jpg']; - addStub.restore(); + expect(bunnyTexture).toBeInstanceOf(Texture); + expect(senseiTexture).toBeInstanceOf(Texture); - expect(spy).to.have.been.calledOnce; - expect(addStub).to.have.been.calledWith( - `${res.name}_image`, - `${path.dirname(res.url)}/${res.data.meta.image}` - ); - expect(res).to.have.property('textures') - .that.is.an('object') - .with.keys(Object.keys(getJsonSpritesheet().frames)) - .and.has.property('0.png') - .that.is.an.instanceof(Texture); + expect(bunnyTexture.baseTexture).toBe(senseiTexture.baseTexture); - expect(res.textures['0.png'].frame.x).to.equal(14); - expect(res.textures['0.png'].frame.y).to.equal(28); - expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3); - expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4); - expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0 - expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0); + expect(bunnyTexture.baseTexture.valid).toBe(true); + expect(bunnyTexture.width).toBe(7); + expect(bunnyTexture.height).toBe(10); - expect(res).to.have.property('spritesheet') - .to.have.property('animations') - .to.have.property('png123'); - expect(res.spritesheet.animations.png123.length).to.equal(3); - expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']); + expect(senseiTexture.baseTexture.valid).toBe(true); + expect(senseiTexture.width).toBe(125); + expect(senseiTexture.height).toBe(125); }); - it('should not load binary images as an image loader type', function (done) + it('should do nothing if the resource is not JSON', async () => { - const loader = new Loader(); + const spriteSheet = await loader.load(`black.txt`); - // provide a mock pre-loader that creates an empty base texture for compressed texture assets - // this is necessary because the SpriteSheetLoader expects a baseTexture on the resource - loader.pre((resource, next) => - { - if (resource.extension === 'crn') - { - resource.texture = Texture.EMPTY; - } - next(); - }) - .add(`atlas_crn`, path.join(__dirname, 'resources', 'atlas_crn.json')) - .add(`atlas`, path.join(__dirname, 'resources', 'building1.json')) - .load((loader, resources) => - { - expect(resources.atlas_image.data).to.be.instanceof(HTMLImageElement); - expect(resources.atlas_crn_image.data).to.not.be.instanceof(HTMLImageElement); - loader.reset(); - done(); - }); + expect(spriteSheet).toBeNull(); }); - it('should dispatch an error failing to load spritesheet image', function (done) + it('should do nothing if the resource is JSON, but improper format', async () => { - const spy = sinon.spy((error, ldr, res) => - { - expect(res.name).to.equal('atlas_error_image'); - expect(res.error).to.equal(error); - expect(error.toString()).to.have.string('Failed to load element using: IMG'); - }); - const loader = new Loader(); + const spriteSheet = await loader.load(`${serverPath}test.json`); - loader.add('atlas_error', path.join(__dirname, 'resources', 'atlas_error.json')); - loader.onError.add(spy); - loader.load((loader, resources) => - { - expect(resources.atlas_error_image.error).to.be.instanceof(Error); - expect(spy.calledOnce).to.be.true; - loader.reset(); - done(); - }); + expect(spriteSheet).not.toBeInstanceOf(Spritesheet); + expect(spriteSheet).toEqual({ testNumber: 23, testString: 'Test String 23' }); }); - it('should build the image url', function () + it('should load a multi packed spritesheet', async () => { - function getPath(url, image) - { - return SpritesheetLoader.getResourcePath({ - url, - data: { meta: { image } }, - }); - } - - let result = getPath('http://some.com/spritesheet.json', 'img.png'); + Cache['_parsers'].push(cacheSpritesheet); - expect(result).to.be.equals('http://some.com/img.png'); + const spritesheet = await loader.load(`${serverPath}multi-pack-0.json`) as Spritesheet; - result = getPath('http://some.com/some/dir/spritesheet.json', 'img.png'); - expect(result).to.be.equals('http://some.com/some/dir/img.png'); + Cache.set('multi-pack-0.json', spritesheet); - result = getPath('http://some.com/some/dir/spritesheet.json', './img.png'); - expect(result).to.be.equals('http://some.com/some/dir/img.png'); + const pack0 = Cache.get('star1.png'); + const pack1 = Cache.get('goldmine_10_5.png'); - result = getPath('http://some.com/some/dir/spritesheet.json', '../img.png'); - expect(result).to.be.equals('http://some.com/some/img.png'); + expect(pack0).toBeInstanceOf(Texture); + expect(pack1).toBeInstanceOf(Texture); - result = getPath('/spritesheet.json', 'img.png'); - expect(result).to.be.equals('/img.png'); + expect(pack0.baseTexture.valid).toBe(true); + expect(pack0.width).toBe(64); + expect(pack0.height).toBe(64); - result = getPath('/some/dir/spritesheet.json', 'img.png'); - expect(result).to.be.equals('/some/dir/img.png'); - - result = getPath('/some/dir/spritesheet.json', './img.png'); - expect(result).to.be.equals('/some/dir/img.png'); - - result = getPath('/some/dir/spritesheet.json', '../img.png'); - expect(result).to.be.equals('/some/img.png'); + expect(pack1.baseTexture.valid).toBe(true); + expect(pack1.width).toBe(190); + expect(pack1.height).toBe(229); }); - // TODO: Test that rectangles are created correctly. - // TODO: Test that bathc processing works correctly. - // TODO: Test that resolution processing works correctly. - // TODO: Test that metadata is honored. - - it('should not add itself via multipack', function (done) + it('should not create multipack resources when related_multi_packs field is missing or the wrong type', async () => { // clear the caches only to avoid cluttering the output clearTextureCache(); - const loader = new Loader(); + const spritesheet = await loader.load(`${serverPath}building1-1.json`) as Spritesheet; + const spritesheet2 = await loader.load(`${serverPath}atlas-multipack-wrong-type.json`) as Spritesheet; + const spritesheet3 = await loader.load(`${serverPath}atlas-multipack-wrong-array.json`) as Spritesheet; - loader.add('atlas_multi_self', path.join(__dirname, 'resources', 'building1-0.json')); - loader.load((loader, resources) => - { - expect(Object.values(resources).filter((r) => r.url.includes('building1-0.json')).length).to.be.equals(1); - loader.reset(); - done(); - }); + expect(spritesheet.linkedSheets.length).toEqual(1); + expect(spritesheet2.linkedSheets.length).toEqual(0); + expect(spritesheet3.linkedSheets.length).toEqual(0); }); - it('should create multipack resources when related_multi_packs field is an array of strings', function (done) + it('should unload a spritesheet', async () => { - // clear the caches only to avoid cluttering the output - clearTextureCache(); + const spriteSheet: Spritesheet = await loader.load(`${serverPath}spritesheet.json`); - const loader = new Loader(); + await loader.unload(`${serverPath}spritesheet.json`); - loader.add('atlas_multi_child_check', path.join(__dirname, 'resources', 'building1-0.json')); - loader.load((loader, resources) => - { - expect(resources.atlas_multi_child_check.children.some((r) => r.url.includes('building1-1.json'))).to.be.true; - loader.reset(); - done(); - }); + expect(spriteSheet.baseTexture).toBe(null); }); - it('should not create multipack resources when related_multi_packs field is missing or the wrong type', function (done) + it('should parse a string sprite sheet correctly', () => { - // clear the caches only to avoid cluttering the output - clearTextureCache(); - - const loader = new Loader(); - - loader.add('atlas_no_multipack', path.join(__dirname, 'resources', 'building1.json')); - loader.add('atlas_multipack_wrong_type', path.join(__dirname, 'resources', 'atlas-multipack-wrong-type.json')); - loader.add('atlas_multipack_wrong_array', path.join(__dirname, 'resources', 'atlas-multipack-wrong-array.json')); - loader.load((loader, resources) => + [ + { + url: 'my-sprite-sheet.json', + pass: false, + }, + { + url: 'my-sprite-sheet@0.5x.webp.json', + pass: true, + result: { + format: 'webp', + resolution: 0.5, + src: 'my-sprite-sheet@0.5x.webp.json', + }, + }, + { + url: 'my-sprite-sheet@2x.png.json', + pass: true, + result: { + format: 'png', + resolution: 2, + src: 'my-sprite-sheet@2x.png.json', + }, + }, + { + url: 'my-sprite-sheet@2x.json', + pass: false, + }, + ].forEach((toTest) => { - expect(resources.atlas_no_multipack.children.length).to.be.equals(1); - expect(resources.atlas_multipack_wrong_type.children.length).to.be.equals(1); - expect(resources.atlas_multipack_wrong_array.children.length).to.be.equals(1); - loader.reset(); - done(); - }); - }); - - it('should build the multipack url', function () - { - let result = url.resolve('http://some.com/spritesheet.json', 'spritesheet-1.json'); - - expect(result).to.be.equals('http://some.com/spritesheet-1.json'); - - result = url.resolve('http://some.com/some/dir/spritesheet.json', 'spritesheet-1.json'); - expect(result).to.be.equals('http://some.com/some/dir/spritesheet-1.json'); - - result = url.resolve('http://some.com/some/dir/spritesheet.json', './spritesheet-1.json'); - expect(result).to.be.equals('http://some.com/some/dir/spritesheet-1.json'); - - result = url.resolve('http://some.com/some/dir/spritesheet.json', '../spritesheet-1.json'); - expect(result).to.be.equals('http://some.com/some/spritesheet-1.json'); - - result = url.resolve('/spritesheet.json', 'spritesheet-1.json'); - expect(result).to.be.equals('/spritesheet-1.json'); - - result = url.resolve('/some/dir/spritesheet.json', 'spritesheet-1.json'); - expect(result).to.be.equals('/some/dir/spritesheet-1.json'); - - result = url.resolve('/some/dir/spritesheet.json', './spritesheet-1.json'); - expect(result).to.be.equals('/some/dir/spritesheet-1.json'); - - result = url.resolve('/some/dir/spritesheet.json', '../spritesheet-1.json'); - expect(result).to.be.equals('/some/spritesheet-1.json'); - }); - - it('should use metadata to load all multipack resources', function (done) - { - // clear the caches only to avoid cluttering the output - clearTextureCache(); + const pass = resolveSpriteSheetUrl.test(toTest.url); - const loader = new Loader(); - const metadata = { key: 'value' }; + expect(pass).toBe(toTest.pass); - loader.add('building1-0', path.join(__dirname, 'resources', 'building1-0.json'), { metadata }); - loader.load((loader, resources) => - { - expect(resources['building1-0'].metadata).to.be.equals(metadata); - expect(resources['building1-1'].metadata).to.be.equals(metadata); - - done(); + if (pass) + { + expect(resolveSpriteSheetUrl.parse(toTest.url)).toEqual(toTest.result); + } }); }); }); - -function createMockResource(type, data) -{ - const name = `${Math.floor(Date.now() * Math.random())}`; - - return { - url: `http://localhost/doesnt_exist/${name}`, - name, - type, - data, - metadata: {}, - }; -} - -function getJsonSpritesheet() -{ - /* eslint-disable */ - return {"frames": { - "0.png": - { - "frame": {"x":14,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14}, - "anchor": {"x":0.3,"y":0.4} - }, - "1.png": - { - "frame": {"x":14,"y":42,"w":12,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, - "sourceSize": {"w":12,"h":14} - }, - "2.png": - { - "frame": {"x":14,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "3.png": - { - "frame": {"x":42,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "4.png": - { - "frame": {"x":28,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "5.png": - { - "frame": {"x":14,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "6.png": - { - "frame": {"x":0,"y":42,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "7.png": - { - "frame": {"x":0,"y":28,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "8.png": - { - "frame": {"x":0,"y":14,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }, - "9.png": - { - "frame": {"x":0,"y":0,"w":14,"h":14}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, - "sourceSize": {"w":14,"h":14} - }}, - "animations": { - "png123": [ "1.png", "2.png", "3.png" ] - }, - "meta": { - "app": "http://www.texturepacker.com", - "version": "1.0", - "image": "hud.png", - "format": "RGBA8888", - "size": {"w":64,"h":64}, - "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" - } - }; - /* eslint-enable */ -} diff --git a/packages/spritesheet/test/resources/atlas.crn b/packages/spritesheet/test/resources/atlas.crn deleted file mode 100644 index d5e78925813452db3cf57f6401c8498d5d39ae0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14681 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 XzswufOu7x--3XBSDlc9kY7q249&?2w diff --git a/packages/spritesheet/test/resources/atlas_crn.json b/packages/spritesheet/test/resources/atlas_crn.json deleted file mode 100644 index 6327c0b04a3..00000000000 --- a/packages/spritesheet/test/resources/atlas_crn.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "meta": { - "image": "atlas.crn", - "size": {"w":256,"h":256}, - "scale": "1" - }, - "frames": { - "resources/test.png": - { - "frame": {"x":2,"y":2,"w":152,"h":188}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":74,"y":36,"w":152,"h":188}, - "sourceSize": {"w":300,"h":225} - }, - "resources/font.png": - { - "frame": {"x":158,"y":2,"w":40,"h":42}, - "rotated": false, - "trimmed": true, - "spriteSourceSize": {"x":2,"y":2,"w":40,"h":42}, - "sourceSize": {"w":43,"h":46} - } - } -} \ No newline at end of file diff --git a/packages/spritesheet/test/resources/atlas_error.json b/packages/spritesheet/test/resources/atlas_error.json deleted file mode 100644 index 531a124558b..00000000000 --- a/packages/spritesheet/test/resources/atlas_error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "frames": { - "boss1.png": { - "frame": {"x":1,"y":1,"w":168,"h":168}, - "rotated": false, - "trimmed": false, - "spriteSourceSize": {"x":0,"y":0,"w":168,"h":168}, - "sourceSize": {"w":168,"h":168} - } - }, - "meta": { - "image": "invalid.png", - "format": "RGBA8888", - "size": {"w":170,"h":170}, - "scale": "1" - } -} \ No newline at end of file diff --git a/packages/spritesheet/test/resources/multi-pack-0.json b/packages/spritesheet/test/resources/multi-pack-0.json new file mode 100644 index 00000000000..e05acdb9da8 --- /dev/null +++ b/packages/spritesheet/test/resources/multi-pack-0.json @@ -0,0 +1,48 @@ +{"frames": { + +"star1.png": +{ + "frame": {"x":0,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star2.png": +{ + "frame": {"x":64,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star3.png": +{ + "frame": {"x":128,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}, +"star4.png": +{ + "frame": {"x":192,"y":0,"w":64,"h":64}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":64,"h":64}, + "sourceSize": {"w":64,"h":64} +}}, +"animations": { + "star": ["star1.png","star2.png","star3.png","star4.png"] +}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "multi-pack-0.png", + "format": "RGBA8888", + "size": {"w":256,"h":64}, + "scale": "1", + "related_multi_packs": [ "multi-pack-1.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:5f1e3e3af16b7f3e5f4097ccfd45634f:8acde9d234ecca966a410602c71bffad:e9ee6f100f514069f43ab3a680b02726$" +} +} diff --git a/packages/spritesheet/test/resources/multi-pack-0.png b/packages/spritesheet/test/resources/multi-pack-0.png new file mode 100644 index 0000000000000000000000000000000000000000..52c1171d0156238ca9f9a7787f047257c63f0ec9 GIT binary patch literal 2435 zcmV-}34Hd6P)UDWP;i z$aG2>p_EJsWz)G+Mku8-GM$ntnNFwG$&^g0)5>&GsZJ)-Y9&&cXMfz2_TJn3@xJdp zAHVbFJRB-@-+O-_?>WEk0|W#F1Ox;G1Ox;G1Ox;G1Ox;G1O%7_^MMBeX;<>Dz=N86 z*$ePS;6q*hv;`jcFT{3$F97Zjyr|$y4&Wj{0-Ol^sNhW&U=iSS;D!If992rb1@Lg- z$7{ZvR(v7Ab%33LCp#_?XBA(T0zdp0=vO5Lvb^2fnZk;LR$&bbIpK zhwL11%mEzsMW6+M8&v`&z*D>2yuDL{Cj@wK7xSg7bmG6o6HnYD9#_A2!Hm1h9Kdma zs{n8LX8zY&yVSqqsRle*-kn(i_5oa}!xK+}q&!*myXOH8XgV;)06r>v_JS{hoo%4( z1o&-%*LbE6u@UC$nE!m+_hnAg zPANQX^p<~HYi$AS7f#19O{d$Th&nRrfxe$>vWd+^Plt09;DZLwd*s6ga5#csch+2d z)0cf}hb$_;i^+FdEBu&YoLy=|nJ)Q+HO=UC!Mx~>VETI${NhxD-@T+Z<)if@ z_&gJn7whs}#aR0OO!1&lW(h6E`@DSf|5;2SQ!!yrDT>NTfLB!1Gs}2RDTrULjXSm*i?Ue31l9+Rrbt30RIBe zWARHzgr9o01JDHk&s&zHffpnTU=4uH)XggZ?*W-j1N5{3SaBfWsQ9x?5nchfSN4BD z0GXc*ZG^J`j##Gk10Zuxs0FYLpx5FTz7J&nmdJ>M4$Q+lhG{zEfTmX03$tCA4GWrf znVSayT(iszEhWvUXLc5jeH!n=# zEu_m>Xi~B&X?<=<9~OnsdtbR}eGU&p+cewi2;`tD{8$pI?8_DfJ?X*AzpAISIubu- z1k(RN>FZvLdU4bNou)HwJO}Wp2MT}DqM!>7f<1AU#d!-H6V8iA0MC{VF(dSMMre35 zwYC&(Ig=;R5@mmbfi5oB`FPD((FvXqEZi+O12jZh0e2kmp-s4(xKt`z z)|T~{t})6@n#*His+8zL7zg$8%nMZfeGYiAApB*}R0zcbRTFunuS*7IV?^qAc4+=s z-vmwyqJPdo-g{nnCPYJh06SDCBRyPenllB=mRfGb5 zhKWiX6B6WWbzRk15-#5CvphPg;b4rEx2A>=*1Kt(k2S5##?`3Id8w1+z4z*r=?}3Qzyl zOMwoVJ{9%}t`=O@mjm{q4!~5o>!|QzuoITtpZTmK zf%69BJ0kq#vpgP~*;1#aSe>7@+#bzAPwK!m?uI-om{yG@ABR2Z1#vJrnY|8%fHre^ zU0j|bsu;#Xs*Ih&Yu`29qsN@^T))HqhYCK83y6bVba*3{cqO^3%9u4>wZ)xja>=v1klk1==!b%ajC#)rJ%UOR87e zzYCrAU0pqBl~?_WDA@5JlHn@bw9DBTgbgAM@Q29)iO8h`&Az>~L4)68Sb z4BNTK(58txxXU(xm#)qK0}jl*X?O<~TFjK(u{-3`TbF6e-YE3CG+VCock2Qqxs>1` zfFE1P?FnT3tg^6$1FF(=Hlh`E(lO0z2{KvZYN$-y?8$YP zgjSD&exd5^r&T&ALIDmB$1El(dcFa4#T4?QpQe8W&9`FC@M{uNVz;`1r&#Bfs!NXP zU5P>KM5W8Zc12gzcVgBhp*<=Ec)Ycl{M;Yor5J|yh}=SKdB&eHdM9I)v?d6YvY@QX zDP@t~bxiMrCUibk6{`6rn_QHUYZs9Ya4405)ogx;kF zoq8wZ74ERFNuNy-=>hwi%-Fw>B3cKU_{I<1N3*rk`>4sZ+I)&=y;Y+`{Zwn^=^Rw< zbxIG3O1Gk(vK&Ymt;GhW|4_#>RS&V1f z{!PxQ)Saw=PC%ms=F92~Mp8`YoW1s4=O^QanX%mgX;qq>N;T$FOyf>%z)Z?zc`zMm z+<*Z6FUPU;q`?9L0s;a80s;a80s;a80s;c0;(rKYI3Kg$!;1g_002ovPDHLkV1nza Bj$i-) literal 0 HcmV?d00001 diff --git a/packages/spritesheet/test/resources/multi-pack-1.json b/packages/spritesheet/test/resources/multi-pack-1.json new file mode 100644 index 00000000000..ff4c21ff7b1 --- /dev/null +++ b/packages/spritesheet/test/resources/multi-pack-1.json @@ -0,0 +1,23 @@ +{"frames": { + +"goldmine_10_5.png": +{ + "frame": {"x":0,"y":0,"w":190,"h":229}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":190,"h":229}, + "sourceSize": {"w":190,"h":229} +}}, +"animations": { +}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.0", + "image": "multi-pack-1.png", + "format": "RGBA8888", + "size": {"w":190,"h":229}, + "scale": "1", + "related_multi_packs": [ "multi-pack-0.json" ], + "smartupdate": "$TexturePacker:SmartUpdate:5f1e3e3af16b7f3e5f4097ccfd45634f:8acde9d234ecca966a410602c71bffad:e9ee6f100f514069f43ab3a680b02726$" +} +} diff --git a/packages/spritesheet/test/resources/multi-pack-1.png b/packages/spritesheet/test/resources/multi-pack-1.png new file mode 100644 index 0000000000000000000000000000000000000000..639b33f660e934acaf06a86ff945d63d730b2e9a GIT binary patch literal 69086 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 s$8|d{ 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 literal 0 HcmV?d00001 diff --git a/packages/spritesheet/test/resources/spritesheet.json b/packages/spritesheet/test/resources/spritesheet.json new file mode 100644 index 00000000000..2b1d2609fdd --- /dev/null +++ b/packages/spritesheet/test/resources/spritesheet.json @@ -0,0 +1,55 @@ +{ + "frames": { + "pic-sensei.jpg": { + "frame": { + "x": 1, + "y": 1, + "w": 125, + "h": 125 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 125, + "h": 125 + }, + "sourceSize": { + "w": 125, + "h": 125 + } + }, + "bunny.png": { + "frame": { + "x": 127, + "y": 1, + "w": 7, + "h": 10 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 7, + "h": 10 + }, + "sourceSize": { + "w": 7, + "h": 10 + } + } + }, + "meta": { + "app": "http://github.com/odrick/free-tex-packer-core", + "version": "0.3.4", + "image": "spritesheet.png", + "format": "RGBA8888", + "size": { + "w": 134, + "h": 126 + }, + "scale": 1 + } +} \ No newline at end of file diff --git a/packages/spritesheet/test/resources/spritesheet.png b/packages/spritesheet/test/resources/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..16a05ed0aed5e6514c77b37294d316fee70c25c8 GIT binary patch literal 3463 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 + kerning: utils.Dict; } /** @memberof PIXI */ @@ -57,14 +53,12 @@ export interface IBitmapFontOptions /** * BitmapFont represents a typeface available for use with the BitmapText class. Use the `install` * method for adding a font to be used. - * * @memberof PIXI */ export class BitmapFont { /** * This character set includes all the letters in the alphabet (both lower- and upper- case). - * * @type {string[][]} * @example * BitmapFont.from("ExampleFont", style, { chars: BitmapFont.ALPHA }) @@ -73,7 +67,6 @@ export class BitmapFont /** * This character set includes all decimal digits (from 0 to 9). - * * @type {string[][]} * @example * BitmapFont.from("ExampleFont", style, { chars: BitmapFont.NUMERIC }) @@ -82,14 +75,12 @@ export class BitmapFont /** * This character set is the union of `BitmapFont.ALPHA` and `BitmapFont.NUMERIC`. - * * @type {string[][]} */ public static readonly ALPHANUMERIC = [['a', 'z'], ['A', 'Z'], ['0', '9'], ' ']; /** * This character set consists of all the ASCII table. - * * @member {string[][]} * @see http://www.asciitable.com/ */ @@ -97,11 +88,10 @@ export class BitmapFont /** * Collection of default options when using `BitmapFont.from`. - * - * @property {number} resolution=1 - * @property {number} textureWidth=512 - * @property {number} textureHeight=512 - * @property {number} padding=4 + * @property {number} [resolution=1] - + * @property {number} [textureWidth=512] - + * @property {number} [textureHeight=512] - + * @property {number} [padding=4] - * @property {string|string[]|string[][]} chars = PIXI.BitmapFont.ALPHANUMERIC */ public static readonly defaultOptions: IBitmapFontOptions = { @@ -113,7 +103,7 @@ export class BitmapFont }; /** Collection of available/installed fonts. */ - public static readonly available: Dict = {}; + public static readonly available: utils.Dict = {}; /** The name of the font face. */ public readonly font: string; @@ -125,10 +115,10 @@ export class BitmapFont public readonly lineHeight: number; /** The map of characters by character code. */ - public readonly chars: Dict; + public readonly chars: utils.Dict; /** The map of base page textures (i.e., sheets of glyphs). */ - public readonly pageTextures: Dict; + public readonly pageTextures: utils.Dict; /** The range of the distance field in pixels. */ public readonly distanceFieldRange: number; @@ -144,14 +134,14 @@ export class BitmapFont * @param ownsTextures - Setting to `true` will destroy page textures * when the font is uninstalled. */ - constructor(data: BitmapFontData, textures: Texture[]|Dict, ownsTextures?: boolean) + constructor(data: BitmapFontData, textures: Texture[] | utils.Dict, ownsTextures?: boolean) { const [info] = data.info; const [common] = data.common; const [page] = data.page; const [distanceField] = data.distanceField; - const res = getResolutionOfUrl(page.file); - const pageTextures: Dict = {}; + const res = utils.getResolutionOfUrl(page.file); + const pageTextures: utils.Dict = {}; this._ownsTextures = ownsTextures; this.font = info.face; @@ -256,19 +246,18 @@ export class BitmapFont /** * Register a new bitmap font. - * * @param data - The * characters map that could be provided as xml or raw string. * @param textures - List of textures for each page. * @param ownsTextures - Set to `true` to destroy page textures * when the font is uninstalled. By default fonts created with * `BitmapFont.from` or from the `BitmapFontLoader` are `true`. - * @return {PIXI.BitmapFont} Result font object with font, size, lineHeight + * @returns {PIXI.BitmapFont} Result font object with font, size, lineHeight * and char fields. */ public static install( - data: string|XMLDocument|BitmapFontData, - textures: Texture|Texture[]|Dict, + data: string | XMLDocument | BitmapFontData, + textures: Texture | Texture[] | utils.Dict, ownsTextures?: boolean ): BitmapFont { @@ -305,7 +294,6 @@ export class BitmapFont /** * Remove bitmap font by name. - * * @param name - Name of the font to uninstall. */ public static uninstall(name: string): void @@ -342,9 +330,8 @@ export class BitmapFont * - {@link PIXI.TextStyle#stroke|stroke} * - {@link PIXI.TextStyle#strokeThickness|strokeThickness} * - {@link PIXI.TextStyle#textBaseline|textBaseline} - * * @param name - The name of the custom font to use with BitmapText. - * @param style - Style options to render with BitmapFont. + * @param textStyle - Style options to render with BitmapFont. * @param options - Setup options for font or name of the font. * @param {string|string[]|string[][]} [options.chars=PIXI.BitmapFont.ALPHANUMERIC] - characters included * in the font set. You can also use ranges. For example, `[['a', 'z'], ['A', 'Z'], "!@#$%^&*()~{}[] "]`. @@ -353,7 +340,7 @@ export class BitmapFont * @param {number} [options.textureWidth=512] - Optional width of atlas, smaller values to reduce memory. * @param {number} [options.textureHeight=512] - Optional height of atlas, smaller values to reduce memory. * @param {number} [options.padding=4] - Padding between glyphs on texture atlas. - * @return Font generated by style options. + * @returns Font generated by style options. * @example * PIXI.BitmapFont.from("TitleFont", { * fontFamily: "Arial", @@ -406,7 +393,7 @@ export class BitmapFont { if (!canvas) { - canvas = document.createElement('canvas'); + canvas = settings.ADAPTER.createCanvas(); canvas.width = textureWidth; canvas.height = textureHeight; diff --git a/packages/text-bitmap/src/BitmapFontData.ts b/packages/text-bitmap/src/BitmapFontData.ts index 49042209a8c..cfc892e9d65 100644 --- a/packages/text-bitmap/src/BitmapFontData.ts +++ b/packages/text-bitmap/src/BitmapFontData.ts @@ -2,7 +2,6 @@ /** * Normalized parsed data from .fnt files. - * * @memberof PIXI */ export class BitmapFontData @@ -37,7 +36,8 @@ export class BitmapFontData } /** @memberof PIXI */ -export interface IBitmapFontDataInfo { +export interface IBitmapFontDataInfo +{ /** Font face */ face: string; @@ -46,13 +46,15 @@ export interface IBitmapFontDataInfo { } /** @memberof PIXI */ -export interface IBitmapFontDataCommon { +export interface IBitmapFontDataCommon +{ /** Line height, in pixels. */ lineHeight: number; } /** @memberof PIXI */ -export interface IBitmapFontDataPage { +export interface IBitmapFontDataPage +{ /** Unique id for bitmap texture */ id: number; @@ -61,7 +63,8 @@ export interface IBitmapFontDataPage { } /** @memberof PIXI */ -export interface IBitmapFontDataChar { +export interface IBitmapFontDataChar +{ /** Unique id of character */ id: number; @@ -91,7 +94,8 @@ export interface IBitmapFontDataChar { } /** @memberof PIXI */ -export interface IBitmapFontDataKerning { +export interface IBitmapFontDataKerning +{ /** First character of pair */ first: number; @@ -103,7 +107,8 @@ export interface IBitmapFontDataKerning { } /** @memberof PIXI */ -export interface IBitmapFontDataDistanceField { +export interface IBitmapFontDataDistanceField +{ /** Type of distance field */ fieldType: string; diff --git a/packages/text-bitmap/src/BitmapFontLoader.ts b/packages/text-bitmap/src/BitmapFontLoader.ts deleted file mode 100644 index 1f55dbe9cad..00000000000 --- a/packages/text-bitmap/src/BitmapFontLoader.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { LoaderResource } from '@pixi/loaders'; -import { autoDetectFormat } from './formats'; -import { BitmapFont } from './BitmapFont'; - -import type { Loader } from '@pixi/loaders'; -import type { Dict } from '@pixi/utils'; -import type { Texture } from '@pixi/core'; - -/** - * {@link PIXI.Loader Loader} middleware for loading - * bitmap-based fonts suitable for using with {@link PIXI.BitmapText}. - * - * @memberof PIXI - */ -export class BitmapFontLoader -{ - /** - * Called when the plugin is installed. - * - * @see PIXI.Loader.registerPlugin - */ - public static add(): void - { - LoaderResource.setExtensionXhrType('fnt', LoaderResource.XHR_RESPONSE_TYPE.TEXT); - } - - /** - * Called after a resource is loaded. - * - * @see PIXI.Loader.loaderMiddleware - * @param {PIXI.LoaderResource} resource - * @param {function} next - */ - static use(this: Loader, resource: LoaderResource, next: (...args: any[]) => void): void - { - const format = autoDetectFormat(resource.data); - - // Resource was not recognised as any of the expected font data format - if (!format) - { - next(); - - return; - } - - const baseUrl = BitmapFontLoader.getBaseUrl(this, resource); - const data = format.parse(resource.data); - const textures: Dict = {}; - - // Handle completed, when the number of textures - // load is the same number as references in the fnt file - const completed = (page: LoaderResource): void => - { - textures[page.metadata.pageFile] = page.texture; - - if (Object.keys(textures).length === data.page.length) - { - resource.bitmapFont = BitmapFont.install(data, textures, true); - next(); - } - }; - - for (let i = 0; i < data.page.length; ++i) - { - const pageFile = data.page[i].file; - const url = baseUrl + pageFile; - let exists = false; - - // incase the image is loaded outside - // using the same loader, resource will be available - for (const name in this.resources) - { - const bitmapResource: LoaderResource = this.resources[name]; - - if (bitmapResource.url === url) - { - bitmapResource.metadata.pageFile = pageFile; - if (bitmapResource.texture) - { - completed(bitmapResource); - } - else - { - bitmapResource.onAfterMiddleware.add(completed); - } - exists = true; - break; - } - } - - // texture is not loaded, we'll attempt to add - // it to the load and add the texture to the list - if (!exists) - { - // Standard loading options for images - const options = { - crossOrigin: resource.crossOrigin, - loadType: LoaderResource.LOAD_TYPE.IMAGE, - metadata: Object.assign( - { pageFile }, - resource.metadata.imageMetadata - ), - parentResource: resource, - }; - - this.add(url, options, completed); - } - } - } - - /** Get folder path from a resource. */ - private static getBaseUrl(loader: Loader, resource: LoaderResource): string - { - let resUrl = !resource.isDataUrl ? BitmapFontLoader.dirname(resource.url) : ''; - - if (resource.isDataUrl) - { - if (resUrl === '.') - { - resUrl = ''; - } - - if (loader.baseUrl && resUrl) - { - // if baseurl has a trailing slash then add one to resUrl so the replace works below - if (loader.baseUrl.charAt(loader.baseUrl.length - 1) === '/') - { - resUrl += '/'; - } - } - } - - // remove baseUrl from resUrl - resUrl = resUrl.replace(loader.baseUrl, ''); - - // if there is an resUrl now, it needs a trailing slash. Ensure that it does if the string isn't empty. - if (resUrl && resUrl.charAt(resUrl.length - 1) !== '/') - { - resUrl += '/'; - } - - return resUrl; - } - - /** - * Replacement for NodeJS's path.dirname - * - * @param {string} url - Path to get directory for - */ - private static dirname(url: string): string - { - const dir = url - .replace(/\\/g, '/') // convert windows notation to UNIX notation, URL-safe because it's a forbidden character - .replace(/\/$/, '') // replace trailing slash - .replace(/\/[^\/]*$/, ''); // remove everything after the last - - // File request is relative, use current directory - if (dir === url) - { - return '.'; - } - // Started with a slash - else if (dir === '') - { - return '/'; - } - - return dir; - } -} diff --git a/packages/text-bitmap/src/BitmapText.ts b/packages/text-bitmap/src/BitmapText.ts index 61a1580e6bb..7101961924d 100644 --- a/packages/text-bitmap/src/BitmapText.ts +++ b/packages/text-bitmap/src/BitmapText.ts @@ -1,20 +1,17 @@ -import { ObservablePoint, Point } from '@pixi/math'; -import { settings } from '@pixi/settings'; import { Mesh, MeshGeometry, MeshMaterial } from '@pixi/mesh'; -import { removeItems } from '@pixi/utils'; import { BitmapFont } from './BitmapFont'; import { splitTextToCharacters, extractCharCode } from './utils'; import msdfFrag from './shader/msdf.frag'; import msdfVert from './shader/msdf.vert'; -import type { Rectangle } from '@pixi/math'; -import { Program, Renderer, Texture } from '@pixi/core'; +import type { Renderer, Rectangle } from '@pixi/core'; +import { Program, Texture, BLEND_MODES, settings, utils, ObservablePoint, Point } from '@pixi/core'; import type { IBitmapTextStyle } from './BitmapTextStyle'; import type { TextStyleAlign } from '@pixi/text'; import { Container } from '@pixi/display'; import type { IDestroyOptions } from '@pixi/display'; -import { BLEND_MODES } from '@pixi/constants'; -interface PageMeshData { +interface PageMeshData +{ index: number; indexCount: number; vertexCount: number; @@ -25,7 +22,8 @@ interface PageMeshData { uvs?: Float32Array; indices?: Uint16Array; } -interface CharRenderData { +interface CharRenderData +{ texture: Texture; line: number; charCode: number; @@ -66,7 +64,6 @@ const charRenderDataPool: CharRenderData[] = []; * align: "right" * }); * ``` - * * @memberof PIXI */ export class BitmapText extends Container @@ -82,22 +79,28 @@ export class BitmapText extends Container public dirty: boolean; /** - * Private tracker for the width of the overall text. + * The resolution / device pixel ratio of the canvas. * + * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually. + * @default PIXI.settings.RESOLUTION + */ + _resolution: number; + _autoResolution: boolean; + + /** + * Private tracker for the width of the overall text. * @private */ protected _textWidth: number; /** * Private tracker for the height of the overall text. - * * @private */ protected _textHeight: number; /** * Private tracker for the current text. - * * @private */ protected _text: string; @@ -106,7 +109,6 @@ export class BitmapText extends Container * The max width of this bitmap text in pixels. If the text provided is longer than the * value provided, line breaks will be automatically inserted in the last whitespace. * Disable by setting value to 0 - * * @private */ protected _maxWidth: number; @@ -114,21 +116,18 @@ export class BitmapText extends Container /** * The max line height. This is useful when trying to use the total height of the Text, * ie: when trying to vertically align. (Internally used) - * * @private */ protected _maxLineHeight: number; /** * Letter spacing. This is useful for setting the space between characters. - * * @private */ protected _letterSpacing: number; /** * Text anchor. - * * @readonly * @private */ @@ -136,21 +135,18 @@ export class BitmapText extends Container /** * Private tracker for the current font name. - * * @private */ protected _fontName: string; /** * Private tracker for the current font size. - * * @private */ protected _fontSize: number; /** * Private tracker for the current text align. - * * @type {string} * @private */ @@ -161,14 +157,12 @@ export class BitmapText extends Container /** * Private tracker for the current tint. - * * @private */ protected _tint = 0xFFFFFF; /** * If true PixiJS will Math.floor() x/y values when rendering. - * * @default PIXI.settings.ROUND_PIXELS */ protected _roundPixels: boolean; @@ -215,13 +209,12 @@ export class BitmapText extends Container this._anchor = new ObservablePoint((): void => { this.dirty = true; }, this, 0, 0); this._roundPixels = settings.ROUND_PIXELS; this.dirty = true; + this._resolution = settings.RESOLUTION; + this._autoResolution = true; this._textureCache = {}; } - /** - * Renders text and updates it when needed. This should only be called - * if the BitmapFont is regenerated. - */ + /** Renders text and updates it when needed. This should only be called if the BitmapFont is regenerated. */ public updateText(): void { const data = BitmapFont.available[this._fontName]; @@ -302,7 +295,8 @@ export class BitmapText extends Container chars.push(charRenderData); - lastLineWidth = charRenderData.position.x + Math.max(charData.xAdvance, charData.texture.orig.width); + lastLineWidth = charRenderData.position.x + + Math.max(charData.xAdvance - charData.xOffset, charData.texture.orig.width); pos.x += charData.xAdvance + this._letterSpacing; maxLineHeight = Math.max(maxLineHeight, (charData.yOffset + charData.texture.height)); prevCharCode = charCode; @@ -310,7 +304,7 @@ export class BitmapText extends Container if (lastBreakPos !== -1 && maxWidth > 0 && pos.x > maxWidth) { ++spacesRemoved; - removeItems(chars, 1 + lastBreakPos - spacesRemoved, 1 + i - lastBreakPos); + utils.removeItems(chars, 1 + lastBreakPos - spacesRemoved, 1 + i - lastBreakPos); i = lastBreakPos; lastBreakPos = -1; @@ -446,7 +440,7 @@ export class BitmapText extends Container // the updated text (if any), removed and return them to the pool. for (let i = 0; i < activePagesMeshData.length; i++) { - if (newPagesMeshData.indexOf(activePagesMeshData[i]) === -1) + if (!newPagesMeshData.includes(activePagesMeshData[i])) { this.removeChild(activePagesMeshData[i].mesh); } @@ -608,6 +602,12 @@ export class BitmapText extends Container _render(renderer: Renderer): void { + if (this._autoResolution && this._resolution !== renderer.resolution) + { + this._resolution = renderer.resolution; + this.dirty = true; + } + // Update the uniform const { distanceFieldRange, distanceFieldType, size } = BitmapFont.available[this._fontName]; @@ -622,9 +622,11 @@ export class BitmapText extends Container const fontScale = this._fontSize / size; + const resolution = renderer._view.resolution; + for (const mesh of this._activePagesMeshData) { - mesh.mesh.shader.uniforms.uFWidth = worldScale * distanceFieldRange * fontScale * renderer.resolution; + mesh.mesh.shader.uniforms.uFWidth = worldScale * distanceFieldRange * fontScale * resolution; } } @@ -633,8 +635,7 @@ export class BitmapText extends Container /** * Validates text before calling parent's getLocalBounds - * - * @return - The rectangular bounding area + * @returns - The rectangular bounding area */ public getLocalBounds(): Rectangle { @@ -645,7 +646,6 @@ export class BitmapText extends Container /** * Updates text when needed - * * @private */ protected validate(): void @@ -659,7 +659,6 @@ export class BitmapText extends Container /** * The tint of the BitmapText object. - * * @default 0xffffff */ public get tint(): number @@ -681,7 +680,6 @@ export class BitmapText extends Container /** * The alignment of the BitmapText object. - * * @member {string} * @default 'left' */ @@ -801,7 +799,6 @@ export class BitmapText extends Container /** * The max line height. This is useful when trying to use the total height of the Text, * i.e. when trying to vertically align. - * * @readonly */ public get maxLineHeight(): number @@ -814,7 +811,6 @@ export class BitmapText extends Container /** * The width of the overall text, different from fontSize, * which is defined in the style object. - * * @readonly */ public get textWidth(): number @@ -844,7 +840,6 @@ export class BitmapText extends Container * Advantages can include sharper image quality (like text) and faster rendering on canvas. * The main disadvantage is movement of objects may appear less smooth. * To set the global default, change {@link PIXI.settings.ROUND_PIXELS} - * * @default PIXI.settings.ROUND_PIXELS */ public get roundPixels(): boolean @@ -864,7 +859,6 @@ export class BitmapText extends Container /** * The height of the overall text, different from fontSize, * which is defined in the style object. - * * @readonly */ public get textHeight(): number @@ -874,6 +868,30 @@ export class BitmapText extends Container return this._textHeight; } + /** + * The resolution / device pixel ratio of the canvas. + * + * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually. + * @default 1 + */ + get resolution(): number + { + return this._resolution; + } + + set resolution(value: number) + { + this._autoResolution = false; + + if (this._resolution === value) + { + return; + } + + this._resolution = value; + this.dirty = true; + } + destroy(options?: boolean | IDestroyOptions): void { const { _textureCache } = this; diff --git a/packages/text-bitmap/src/BitmapTextStyle.ts b/packages/text-bitmap/src/BitmapTextStyle.ts index c995d0de536..f0fa4a046d1 100644 --- a/packages/text-bitmap/src/BitmapTextStyle.ts +++ b/packages/text-bitmap/src/BitmapTextStyle.ts @@ -1,6 +1,7 @@ import type { TextStyleAlign } from '@pixi/text'; -export interface IBitmapTextStyle { +export interface IBitmapTextStyle +{ fontName: string; fontSize: number; tint: number; @@ -9,7 +10,8 @@ export interface IBitmapTextStyle { maxWidth: number; } -export interface IBitmapTextFontDescriptor { +export interface IBitmapTextFontDescriptor +{ name: string; size: number; } diff --git a/packages/text-bitmap/src/formats/TextFormat.ts b/packages/text-bitmap/src/formats/TextFormat.ts index e93b253fa46..f7d62dab9f0 100644 --- a/packages/text-bitmap/src/formats/TextFormat.ts +++ b/packages/text-bitmap/src/formats/TextFormat.ts @@ -4,7 +4,8 @@ import { BitmapFontData } from '../BitmapFontData'; * Internal data format used to convert to BitmapFontData. * @private */ -interface IBitmapFontRawData { +export interface IBitmapFontRawData +{ info: { face: string; size: string; @@ -44,27 +45,24 @@ interface IBitmapFontRawData { /** * BitmapFont format that's Text-based. - * * @private */ export class TextFormat { /** * Check if resource refers to txt font data. - * * @param data - * @return - True if resource could be treated as font data, false otherwise. + * @returns - True if resource could be treated as font data, false otherwise. */ static test(data: unknown): boolean { - return typeof data === 'string' && data.indexOf('info face=') === 0; + return typeof data === 'string' && data.startsWith('info face='); } /** * Convert text font data to a javascript object. - * * @param txt - Raw string data to be converted - * @return - Parsed font data + * @returns - Parsed font data */ static parse(txt: string): BitmapFontData { diff --git a/packages/text-bitmap/src/formats/XMLFormat.ts b/packages/text-bitmap/src/formats/XMLFormat.ts index 0d5930e4ab6..adc33e4367f 100644 --- a/packages/text-bitmap/src/formats/XMLFormat.ts +++ b/packages/text-bitmap/src/formats/XMLFormat.ts @@ -2,16 +2,14 @@ import { BitmapFontData } from '../BitmapFontData'; /** * BitmapFont format that's XML-based. - * * @private */ export class XMLFormat { /** * Check if resource refers to xml font data. - * * @param data - * @return - True if resource could be treated as font data, false otherwise. + * @returns - True if resource could be treated as font data, false otherwise. */ static test(data: unknown): boolean { @@ -22,9 +20,8 @@ export class XMLFormat /** * Convert the XML into BitmapFontData that we can use. - * * @param xml - * @return - Data to use for BitmapFont + * @returns - Data to use for BitmapFont */ static parse(xml: XMLDocument): BitmapFontData { diff --git a/packages/text-bitmap/src/formats/XMLStringFormat.ts b/packages/text-bitmap/src/formats/XMLStringFormat.ts index 5fb572120d4..cffc0c2177f 100644 --- a/packages/text-bitmap/src/formats/XMLStringFormat.ts +++ b/packages/text-bitmap/src/formats/XMLStringFormat.ts @@ -1,22 +1,20 @@ -import { BitmapFontData } from '../BitmapFontData'; +import type { BitmapFontData } from '../BitmapFontData'; import { XMLFormat } from './XMLFormat'; /** * BitmapFont format that's XML-based. - * * @private */ export class XMLStringFormat { /** * Check if resource refers to text xml font data. - * * @param data - * @return - True if resource could be treated as font data, false otherwise. + * @returns - True if resource could be treated as font data, false otherwise. */ static test(data: unknown): boolean { - if (typeof data === 'string' && data.indexOf('') > -1) + if (typeof data === 'string' && data.includes('')) { const xml = new globalThis.DOMParser().parseFromString(data, 'text/xml'); @@ -28,9 +26,8 @@ export class XMLStringFormat /** * Convert the text XML into BitmapFontData that we can use. - * * @param xmlTxt - * @return - Data to use for BitmapFont + * @returns - Data to use for BitmapFont */ static parse(xmlTxt: string): BitmapFontData { diff --git a/packages/text-bitmap/src/formats/index.ts b/packages/text-bitmap/src/formats/index.ts index af916c7e667..6478c99e1fc 100644 --- a/packages/text-bitmap/src/formats/index.ts +++ b/packages/text-bitmap/src/formats/index.ts @@ -13,7 +13,7 @@ const formats = [ * Auto-detect BitmapFont parsing format based on data. * @private * @param {any} data - Data to detect format - * @return {any} Format or null + * @returns {any} Format or null */ export function autoDetectFormat(data: unknown): typeof formats[number] | null { @@ -27,3 +27,6 @@ export function autoDetectFormat(data: unknown): typeof formats[number] | null return null; } + +export type { IBitmapFontRawData } from './TextFormat'; +export { TextFormat, XMLFormat, XMLStringFormat }; diff --git a/packages/text-bitmap/src/index.ts b/packages/text-bitmap/src/index.ts index b008c048ea1..0697fd9c95c 100644 --- a/packages/text-bitmap/src/index.ts +++ b/packages/text-bitmap/src/index.ts @@ -1,5 +1,6 @@ -export * from './BitmapText'; -export * from './BitmapFontLoader'; export * from './BitmapFont'; export * from './BitmapFontData'; +export * from './BitmapText'; export * from './BitmapTextStyle'; +export * from './formats'; +export * from './loadBitmapFont'; diff --git a/packages/text-bitmap/src/loadBitmapFont.ts b/packages/text-bitmap/src/loadBitmapFont.ts new file mode 100644 index 00000000000..9ae1d0996c8 --- /dev/null +++ b/packages/text-bitmap/src/loadBitmapFont.ts @@ -0,0 +1,66 @@ +import type { Texture } from '@pixi/core'; +import { settings, utils, extensions, ExtensionType } from '@pixi/core'; + +import type { LoadAsset, Loader, LoaderParser } from '@pixi/assets'; +import { LoaderParserPriority } from '@pixi/assets'; +import { BitmapFont } from './BitmapFont'; +import type { BitmapFontData } from './BitmapFontData'; +import { TextFormat, XMLStringFormat } from './formats'; + +const validExtensions = ['.xml', '.fnt']; + +/** simple loader plugin for loading in bitmap fonts! */ +export const loadBitmapFont = { + extension: { + type: ExtensionType.LoadParser, + priority: LoaderParserPriority.Normal, + }, + + test(url: string): boolean + { + return validExtensions.includes(utils.path.extname(url)); + }, + + async testParse(data: string): Promise + { + return TextFormat.test(data) || XMLStringFormat.test(data); + }, + + async parse(asset: string, data: LoadAsset, loader: Loader): Promise + { + const fontData: BitmapFontData = TextFormat.test(asset) + ? TextFormat.parse(asset) + : XMLStringFormat.parse(asset); + + const { src } = data; + const { page: pages } = fontData; + const textureUrls = []; + + for (let i = 0; i < pages.length; ++i) + { + const pageFile = pages[i].file; + const imagePath = utils.path.join(utils.path.dirname(src), pageFile); + + textureUrls.push(imagePath); + } + + const loadedTextures = await loader.load(textureUrls) as Record; + const textures = textureUrls.map((url) => loadedTextures[url]); + + return BitmapFont.install(fontData, textures, true); + }, + + async load(url: string, _options: LoadAsset): Promise + { + const response = await settings.ADAPTER.fetch(url); + + return response.text(); + }, + + unload(bitmapFont: BitmapFont): void + { + bitmapFont.destroy(); + } +} as LoaderParser; + +extensions.add(loadBitmapFont); diff --git a/packages/text-bitmap/src/utils/drawGlyph.ts b/packages/text-bitmap/src/utils/drawGlyph.ts index d1973509b76..3f841dbaae8 100644 --- a/packages/text-bitmap/src/utils/drawGlyph.ts +++ b/packages/text-bitmap/src/utils/drawGlyph.ts @@ -1,5 +1,5 @@ import { generateFillStyle } from './generateFillStyle'; -import { hex2rgb, string2hex } from '@pixi/utils'; +import { utils } from '@pixi/core'; import type { TextMetrics, TextStyle } from '@pixi/text'; // TODO: Prevent code duplication b/w drawGlyph & Text#updateText @@ -8,7 +8,6 @@ import type { TextMetrics, TextStyle } from '@pixi/text'; * Draws the glyph `metrics.text` on the given canvas. * * Ignored because not directly exposed. - * * @ignore * @param {HTMLCanvasElement} canvas * @param {CanvasRenderingContext2D} context @@ -50,7 +49,7 @@ export function drawGlyph( if (style.dropShadow) { const dropShadowColor = style.dropShadowColor; - const rgb = hex2rgb(typeof dropShadowColor === 'number' ? dropShadowColor : string2hex(dropShadowColor)); + const rgb = utils.hex2rgb(typeof dropShadowColor === 'number' ? dropShadowColor : utils.string2hex(dropShadowColor)); const dropShadowBlur = style.dropShadowBlur * resolution; const dropShadowDistance = style.dropShadowDistance * resolution; diff --git a/packages/text-bitmap/src/utils/extractCharCode.ts b/packages/text-bitmap/src/utils/extractCharCode.ts index 69e289ab4ad..03d43da9439 100644 --- a/packages/text-bitmap/src/utils/extractCharCode.ts +++ b/packages/text-bitmap/src/utils/extractCharCode.ts @@ -1,5 +1,6 @@ /** * Ponyfill for IE because it doesn't support `codePointAt` + * @param str * @private */ export function extractCharCode(str: string): number diff --git a/packages/text-bitmap/src/utils/generateFillStyle.ts b/packages/text-bitmap/src/utils/generateFillStyle.ts index d33734833d3..d7a883adf0c 100644 --- a/packages/text-bitmap/src/utils/generateFillStyle.ts +++ b/packages/text-bitmap/src/utils/generateFillStyle.ts @@ -1,14 +1,18 @@ -import { TextStyle, TextMetrics, TEXT_GRADIENT } from '@pixi/text'; +import type { TextStyle, TextMetrics } from '@pixi/text'; +import { TEXT_GRADIENT } from '@pixi/text'; // TODO: Prevent code duplication b/w generateFillStyle & Text#generateFillStyle /** * Generates the fill style. Can automatically generate a gradient based on the fill style being an array - * * @private + * @param canvas + * @param context * @param {object} style - The style. + * @param resolution * @param {string[]} lines - The lines of text. - * @return {string|number|CanvasGradient} The fill style + * @param metrics + * @returns {string|number|CanvasGradient} The fill style */ export function generateFillStyle( canvas: HTMLCanvasElement, @@ -17,12 +21,12 @@ export function generateFillStyle( resolution: number, lines: string[], metrics: TextMetrics -): string|CanvasGradient|CanvasPattern +): string | CanvasGradient | CanvasPattern { // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as // the setter converts to string. See this thread for more details: // https://github.com/microsoft/TypeScript/issues/2521 - const fillStyle: string|string[]|CanvasGradient|CanvasPattern = style.fill as any; + const fillStyle: string | string[] | CanvasGradient | CanvasPattern = style.fill as any; if (!Array.isArray(fillStyle)) { @@ -35,7 +39,7 @@ export function generateFillStyle( // the gradient will be evenly spaced out according to how large the array is. // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75 - let gradient: string[]|CanvasGradient; + let gradient: string[] | CanvasGradient; // a dropshadow will enlarge the canvas and result in the gradient being // generated with the incorrect dimensions diff --git a/packages/text-bitmap/src/utils/resolveCharacters.ts b/packages/text-bitmap/src/utils/resolveCharacters.ts index 6525d5945e0..d5fe9dfb0db 100644 --- a/packages/text-bitmap/src/utils/resolveCharacters.ts +++ b/packages/text-bitmap/src/utils/resolveCharacters.ts @@ -4,10 +4,9 @@ import { splitTextToCharacters } from './splitTextToCharacters'; * Processes the passed character set data and returns a flattened array of all the characters. * * Ignored because not directly exposed. - * * @ignore * @param {string | string[] | string[][] } chars - * @returns {string[]} + * @returns {string[]} the flattened array of characters */ export function resolveCharacters(chars: string | (string | string[])[]): string[] { diff --git a/packages/text-bitmap/src/utils/splitTextToCharacters.ts b/packages/text-bitmap/src/utils/splitTextToCharacters.ts index 7156c4a940e..78d13c7c29a 100644 --- a/packages/text-bitmap/src/utils/splitTextToCharacters.ts +++ b/packages/text-bitmap/src/utils/splitTextToCharacters.ts @@ -1,5 +1,6 @@ /** * Ponyfill for IE because it doesn't support `Array.from` + * @param text * @private */ export function splitTextToCharacters(text: string): string[] diff --git a/packages/text-bitmap/test/BitmapFont.tests.ts b/packages/text-bitmap/test/BitmapFont.tests.ts index f482280b5c8..7cf64c926fb 100644 --- a/packages/text-bitmap/test/BitmapFont.tests.ts +++ b/packages/text-bitmap/test/BitmapFont.tests.ts @@ -1,11 +1,10 @@ import { BitmapFont } from '@pixi/text-bitmap'; -import { expect } from 'chai'; -describe('BitmapFont', function () +describe('BitmapFont', () => { - describe('from', function () + describe('from', () => { - afterEach(function () + afterEach(() => { for (const name in BitmapFont.available) { @@ -13,53 +12,56 @@ describe('BitmapFont', function () } }); - it('should throw for missing name', function () + it('should throw for missing name', () => { - expect(() => BitmapFont.from()).to.throw; + // @ts-expect-error - testing for error + expect(() => BitmapFont.from()).toThrow(); }); + // eslint-disable-next-line func-names it('should register the font if a name is provided', function () { - this.timeout(8000); - this.slow(4000); + jest.setTimeout(8000); - expect(BitmapFont.available.foo).to.be.undefined; + expect(BitmapFont.available.foo).toBeUndefined(); const font = BitmapFont.from('foo'); - expect(BitmapFont.available.foo).to.equal(font); + expect(BitmapFont.available.foo).toEqual(font); }); - it('should draw all characters in a provided range', function () + it('should draw all characters in a provided range', () => { const font = BitmapFont.from('foo', {}, { chars: [['a', 'z']] }); - expect(Object.keys(font.chars).length).to.equal(26); + expect(Object.keys(font.chars).length).toEqual(26); }); - it('should draw emojis', function () + it('should draw emojis', () => { const emojis = ['🔥', '🌏', '😀']; const font = BitmapFont.from('foo', {}, { chars: [emojis.join('')] }); - expect(Object.keys(font.chars).length).to.equal(emojis.length); + expect(Object.keys(font.chars).length).toEqual(emojis.length); for (const emoji of emojis) { - expect(font.chars).to.have.property(emoji.codePointAt(0)); + const char = String(emoji.codePointAt(0)); + + expect(font.chars).toHaveProperty(char); } }); - it('should throw an error when an invalid range is given', function () + it('should throw an error when an invalid range is given', () => { - expect(() => BitmapFont.from('foo', {}, { chars: [['l', 'i', 'm']] })).to.throw; + expect(() => BitmapFont.from('foo', {}, { chars: [['l', 'i', 'm']] })).toThrow(); }); - it('should throw an error when an invalid start/end of range', function () + it('should throw an error when an invalid start/end of range', () => { - expect(() => BitmapFont.from('foo', {}, { chars: [['z', 'a']] })).to.throw; + expect(() => BitmapFont.from('foo', {}, { chars: [['z', 'a']] })).toThrow(); }); - it('should render resolution with proportional size', function () + it('should render resolution with proportional size', () => { const fontRes1 = BitmapFont.from('foo', {}, { chars: 'a' }); const fontRes2 = BitmapFont.from('bar', {}, { chars: 'a', resolution: 2 }); @@ -67,25 +69,25 @@ describe('BitmapFont', function () // BitmapFont.from IDs are charCodes const id = 'a'.charCodeAt(0); - expect(fontRes1.chars[id].texture.baseTexture.resolution).to.equal(1); - expect(fontRes2.chars[id].texture.baseTexture.resolution).to.equal(2); + expect(fontRes1.chars[id].texture.baseTexture.resolution).toEqual(1); + expect(fontRes2.chars[id].texture.baseTexture.resolution).toEqual(2); }); - it('should override and replace font', function () + it('should override and replace font', () => { const id = 'a'.charCodeAt(0); BitmapFont.from('foo', {}, { chars: 'a' }); - expect(Object.keys(BitmapFont.available.foo.chars).length).to.equal(1); + expect(Object.keys(BitmapFont.available.foo.chars).length).toEqual(1); BitmapFont.from('foo', {}, { chars: 'bc' }); - expect(Object.keys(BitmapFont.available.foo.chars).length).to.equal(2); - expect(BitmapFont.available.foo.chars[id]).to.be.undefined; + expect(Object.keys(BitmapFont.available.foo.chars).length).toEqual(2); + expect(BitmapFont.available.foo.chars[id]).toBeUndefined(); }); - it('should throw an error when no characters are passed', function () + it('should throw an error when no characters are passed', () => { - expect(() => BitmapFont.from('foo', {}, { chars: [] })).to.throw; + expect(() => BitmapFont.from('foo', {}, { chars: [] })).toThrow(); }); }); }); diff --git a/packages/text-bitmap/test/BitmapFontLoader.tests.ts b/packages/text-bitmap/test/BitmapFontLoader.tests.ts index 1506fed45ab..846d6946647 100644 --- a/packages/text-bitmap/test/BitmapFontLoader.tests.ts +++ b/packages/text-bitmap/test/BitmapFontLoader.tests.ts @@ -1,16 +1,23 @@ -import path from 'path'; -import fs from 'fs'; -import { Loader } from '@pixi/loaders'; -import { BaseTextureCache, TextureCache, destroyTextureCache } from '@pixi/utils'; -import { Texture, BaseTexture } from '@pixi/core'; -import { Spritesheet } from '@pixi/spritesheet'; -import { BitmapFont, BitmapFontLoader } from '@pixi/text-bitmap'; -import sinon from 'sinon'; -import { expect } from 'chai'; - -describe('BitmapFontLoader', function () +import { Cache, loadTextures, loadTxt } from '@pixi/assets'; +import type { ImageResource, Texture } from '@pixi/core'; +import { BitmapFont, loadBitmapFont } from '@pixi/text-bitmap'; +import { BaseTextureCache, TextureCache } from '@pixi/utils'; +import { Loader } from '../../assets/src/loader/Loader'; + +describe('BitmapFontLoader', () => { - afterEach(function () + let loader: Loader; + const serverPath = process.env.GITHUB_ACTIONS + ? `https://raw.githubusercontent.com/pixijs/pixijs/${process.env.GITHUB_SHA}/packages/text-bitmap/test/resources/` + : 'http://localhost:8080/text-bitmap/test/resources/'; + + beforeEach(() => + { + Cache.reset(); + loader.reset(); + }); + + afterEach(() => { for (const font in BitmapFont.available) { @@ -26,646 +33,348 @@ describe('BitmapFontLoader', function () } }); - before(function (done) - { - const resolveURL = (url) => path.resolve(this.resources, url); - - BitmapFontLoader.add(); - - this.resources = path.join(__dirname, 'resources'); - this.fontXML = null; - this.fontTXT = null; - this.fontScaledXML = null; - this.fontImage = null; - this.fontScaledImage = null; - this.atlasImage = null; - this.atlasScaledImage = null; - this.sdfXML = null; - this.msdfXML = null; - this.sdfImage = null; - this.msdfImage = null; - this.atlasJSON = require(resolveURL('atlas.json')); // eslint-disable-line global-require - this.atlasScaledJSON = require(resolveURL('atlas@0.5x.json')); // eslint-disable-line global-require - - const loadXML = (url) => new Promise((resolve) => - fs.readFile(resolveURL(url), 'utf8', (err, data) => - { - expect(err).to.be.null; - resolve((new window.DOMParser()).parseFromString(data, 'text/xml')); - })); - - const loadTxt = (url) => new Promise((resolve) => - fs.readFile(resolveURL(url), 'utf8', (err, data) => - { - expect(err).to.be.null; - resolve(data); - })); - - const loadImage = (url) => new Promise((resolve) => - { - const image = new Image(); - - image.onload = () => resolve(image); - image.src = resolveURL(url); - }); - - Promise.all([ - loadTxt('bmtxt-test.txt'), - loadXML('font.fnt'), - loadTxt('font-text.fnt'), - loadTxt('font-random-args.fnt'), - loadXML('font@0.5x.fnt'), - loadXML('sdf.fnt'), - loadXML('msdf.fnt'), - loadImage('bmtxt-test.png'), - loadImage('font.png'), - loadImage('font@0.5x.png'), - loadImage('atlas.png'), - loadImage('atlas@0.5x.png'), - loadImage('sdf.png'), - loadImage('msdf.png'), - ]).then(([ - fontTXT, - fontXML, - fontText, - fontRandomArgs, - fontScaledXML, - sdfXML, - msdfXML, - fontTXTImage, - fontImage, - fontScaledImage, - atlasImage, - atlasScaledImage, - sdfImage, - msdfImage, - ]) => - { - this.fontTXT = fontTXT; - this.fontXML = fontXML; - this.fontText = fontText; - this.fontRandomArgs = fontRandomArgs; - this.fontScaledXML = fontScaledXML; - this.sdfXML = sdfXML; - this.msdfXML = msdfXML; - this.fontTXTImage = fontTXTImage; - this.fontImage = fontImage; - this.fontScaledImage = fontScaledImage; - this.atlasImage = atlasImage; - this.atlasScaledImage = atlasScaledImage; - this.sdfImage = sdfImage; - this.msdfImage = msdfImage; - done(); - }); - }); - - it('should exist and return a function', function () - { - expect(BitmapFontLoader).to.not.be.undefined; - expect(BitmapFontLoader.use).to.be.a('function'); - }); - - it('should process dirname correctly', function () + beforeAll(() => { - const { dirname } = BitmapFontLoader; - - expect(dirname('file.fnt')).to.equal('.'); - expect(dirname('/file.fnt')).to.equal('/'); - expect(dirname('foo/bar/file.fnt')).to.equal('foo/bar'); - expect(dirname('/foo/bar/file.fnt')).to.equal('/foo/bar'); - expect(dirname('../file.fnt')).to.equal('..'); + loader = new Loader(); + loader['_parsers'].push(loadTxt, loadTextures, loadBitmapFont); }); - it('should do nothing if the resource is not XML/TXT font data', function () + it('should do nothing if the resource is not XML/TXT font data', async () => { - const spy = sinon.spy(); - const res = {}; - - BitmapFontLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.textures).to.be.undefined; + expect(loadBitmapFont.test('notAFont.png')).toBe(false); + expect(await loadBitmapFont.testParse('notAFont.png')).toBe(false); }); - it('should do nothing if the resource is not properly formatted XML', function () + it('should do nothing if the resource is not properly formatted', async () => { - const spy = sinon.spy(); - const res = { data: document.createDocumentFragment() }; - - BitmapFontLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.textures).to.be.undefined; + expect(await loadBitmapFont.testParse( + 'Have a good day!!' + )).toBe(false); + expect(await loadBitmapFont.testParse( + 'abcdefg' + )).toBe(false); }); - it('should do nothing if the resource is not properly formatted TXT', function () + it('should properly register bitmap font', async () => { - const spy = sinon.spy(); - const res = { data: 'abcdefgh' }; - - BitmapFontLoader.use(res, spy); - - expect(spy).to.have.been.calledOnce; - expect(res.textures).to.be.undefined; - }); - - // TODO: Test the texture cache code path. - // TODO: Test the loading texture code path. - // TODO: Test data-url code paths. + const font = await loader.load(`${serverPath}font.fnt`); - it('should properly register bitmap font', function (done) - { - const texture = Texture.from(this.fontImage); - const font = BitmapFont.install(this.fontXML, texture); - - expect(font).to.be.an('object'); - expect(BitmapFont.available.font).to.equal(font); - expect(font).to.have.property('chars'); + expect(font).toBeObject(); + expect(BitmapFont.available.font).toEqual(font); + expect(font).toHaveProperty('chars'); const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charA.texture.frame.x).to.equal(2); - expect(charA.texture.frame.y).to.equal(2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); + const charATexture = charA.texture as Texture; + + expect(charA).toBeDefined(); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charATexture.frame.x).toEqual(2); + expect(charATexture.frame.y).toEqual(2); + expect(charATexture.frame.width).toEqual(19); + expect(charATexture.frame.height).toEqual(20); const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charB.texture.frame.x).to.equal(2); - expect(charB.texture.frame.y).to.equal(24); - expect(charB.texture.frame.width).to.equal(15); - expect(charB.texture.frame.height).to.equal(20); + const charBTexture = charB.texture as Texture; + + expect(charB).toBeDefined(); + expect(charBTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charBTexture.frame.x).toEqual(2); + expect(charBTexture.frame.y).toEqual(24); + expect(charBTexture.frame.width).toEqual(15); + expect(charBTexture.frame.height).toEqual(20); const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charC.texture.frame.x).to.equal(23); - expect(charC.texture.frame.y).to.equal(2); - expect(charC.texture.frame.width).to.equal(18); - expect(charC.texture.frame.height).to.equal(20); + const charCTexture = charC.texture as Texture; + + expect(charC).toBeDefined(); + expect(charCTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charCTexture.frame.x).toEqual(23); + expect(charCTexture.frame.y).toEqual(2); + expect(charCTexture.frame.width).toEqual(18); + expect(charCTexture.frame.height).toEqual(20); const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charD.texture.frame.x).to.equal(19); - expect(charD.texture.frame.y).to.equal(24); - expect(charD.texture.frame.width).to.equal(17); - expect(charD.texture.frame.height).to.equal(20); + const charDTexture = charD.texture as Texture; + + expect(charD).toBeDefined(); + expect(charDTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charDTexture.frame.x).toEqual(19); + expect(charDTexture.frame.y).toEqual(24); + expect(charDTexture.frame.width).toEqual(17); + expect(charDTexture.frame.height).toEqual(20); const charE = font.chars['E'.charCodeAt(0)]; - expect(charE).to.be.undefined; - done(); + expect(charE).toBeUndefined(); }); - it('should properly register bitmap font based on txt data', function (done) + it('should properly register bitmap font based on txt data', async () => { - const texture = Texture.from(this.fontTXTImage); - const font = BitmapFont.install(this.fontTXT, texture); + const font = await loader.load(`${serverPath}bmtxt-test.txt`); - expect(font).to.be.an('object'); - expect(font).to.have.property('chars'); + expect(font).toBeObject(); + expect(font).toHaveProperty('chars'); const charA = font.chars['A'.charCodeAt(0)]; + const charATexture = charA.texture as Texture; - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.fontTXTImage); - expect(charA.texture.frame.x).to.equal(1); - expect(charA.texture.frame.y).to.equal(179); - expect(charA.texture.frame.width).to.equal(38); - expect(charA.texture.frame.height).to.equal(28); - const charB = font.chars['B'.charCodeAt(0)]; + expect(charA).toBeDefined(); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}bmGlyph-test.png`); + expect(charATexture.frame.x).toEqual(1); + expect(charATexture.frame.y).toEqual(179); + expect(charATexture.frame.width).toEqual(38); + expect(charATexture.frame.height).toEqual(28); - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.fontTXTImage); - expect(charB.texture.frame.x).to.equal(52); - expect(charB.texture.frame.y).to.equal(146); - expect(charB.texture.frame.width).to.equal(34); - expect(charB.texture.frame.height).to.equal(28); + const charB = font.chars['B'.charCodeAt(0)]; + const charBTexture = charB.texture as Texture; + + expect(charB).toBeDefined(); + expect(charBTexture.baseTexture.resource.src).toEqual(`${serverPath}bmGlyph-test.png`); + expect(charBTexture.frame.x).toEqual(52); + expect(charBTexture.frame.y).toEqual(146); + expect(charBTexture.frame.width).toEqual(34); + expect(charBTexture.frame.height).toEqual(28); const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.fontTXTImage); - expect(charC.texture.frame.x).to.equal(52); - expect(charC.texture.frame.y).to.equal(117); - expect(charC.texture.frame.width).to.equal(34); - expect(charC.texture.frame.height).to.equal(28); + const charCTexture = charC.texture as Texture; + + expect(charC).toBeDefined(); + expect(charCTexture.baseTexture.resource.src).toEqual(`${serverPath}bmGlyph-test.png`); + expect(charCTexture.frame.x).toEqual(52); + expect(charCTexture.frame.y).toEqual(117); + expect(charCTexture.frame.width).toEqual(34); + expect(charCTexture.frame.height).toEqual(28); const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.fontTXTImage); - expect(charD.texture.frame.x).to.equal(52); - expect(charD.texture.frame.y).to.equal(88); - expect(charD.texture.frame.width).to.equal(34); - expect(charD.texture.frame.height).to.equal(28); + const charDTexture = charD.texture as Texture; + + expect(charD).toBeDefined(); + expect(charDTexture.baseTexture.resource.src).toEqual(`${serverPath}bmGlyph-test.png`); + expect(charDTexture.frame.x).toEqual(52); + expect(charDTexture.frame.y).toEqual(88); + expect(charDTexture.frame.width).toEqual(34); + expect(charDTexture.frame.height).toEqual(28); const charUndefined = font.chars['£'.charCodeAt(0)]; - expect(charUndefined).to.be.undefined; - done(); + expect(charUndefined).toBeUndefined(); }); - it('should properly register SCALED bitmap font', function (done) + it('should properly register bitmap font based on text format', async () => { - const baseTexture = new BaseTexture(this.fontScaledImage); - - baseTexture.setResolution(0.5); + const font = await loader.load(`${serverPath}font-text.fnt`); - const texture = new Texture(baseTexture); - const font = BitmapFont.install(this.fontScaledXML, texture); - - expect(font).to.be.an('object'); - expect(BitmapFont.available.font).to.equal(font); - expect(font).to.have.property('chars'); + expect(font).toBeObject(); + expect(BitmapFont.available.fontText).toEqual(font); + expect(font).toHaveProperty('chars'); const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.fontScaledImage); - expect(charA.texture.frame.x).to.equal(4); // 2 / 0.5 - expect(charA.texture.frame.y).to.equal(4); // 2 / 0.5 - expect(charA.texture.frame.width).to.equal(38); // 19 / 0.5 - expect(charA.texture.frame.height).to.equal(40); // 20 / 0.5 + const charATexture = charA.texture as Texture; + + expect(charA).toBeDefined(); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charATexture.frame.x).toEqual(2); + expect(charATexture.frame.y).toEqual(2); + expect(charATexture.frame.width).toEqual(19); + expect(charATexture.frame.height).toEqual(20); const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.fontScaledImage); - expect(charB.texture.frame.x).to.equal(4); // 2 / 0.5 - expect(charB.texture.frame.y).to.equal(48); // 24 / 0.5 - expect(charB.texture.frame.width).to.equal(30); // 15 / 0.5 - expect(charB.texture.frame.height).to.equal(40); // 20 / 0.5 + const charBTexture = charB.texture as Texture; + + expect(charB).toBeDefined(); + expect(charBTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charBTexture.frame.x).toEqual(2); + expect(charBTexture.frame.y).toEqual(24); + expect(charBTexture.frame.width).toEqual(15); + expect(charBTexture.frame.height).toEqual(20); const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.fontScaledImage); - expect(charC.texture.frame.x).to.equal(46); // 23 / 0.5 - expect(charC.texture.frame.y).to.equal(4); // 2 / 0.5 - expect(charC.texture.frame.width).to.equal(36); // 18 / 0.5 - expect(charC.texture.frame.height).to.equal(40); // 20 / 0.5 + const charCTexture = charC.texture as Texture; + + expect(charC).toBeDefined(); + expect(charCTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charCTexture.frame.x).toEqual(23); + expect(charCTexture.frame.y).toEqual(2); + expect(charCTexture.frame.width).toEqual(18); + expect(charCTexture.frame.height).toEqual(20); const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.fontScaledImage); - expect(charD.texture.frame.x).to.equal(38); // 19 / 0.5 - expect(charD.texture.frame.y).to.equal(48); // 24 / 0.5 - expect(charD.texture.frame.width).to.equal(34); // 17 / 0.5 - expect(charD.texture.frame.height).to.equal(40); // 20 / 0.5 + const charDTexture = charD.texture as Texture; + + expect(charD).toBeDefined(); + expect(charDTexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charDTexture.frame.x).toEqual(19); + expect(charDTexture.frame.y).toEqual(24); + expect(charDTexture.frame.width).toEqual(17); + expect(charDTexture.frame.height).toEqual(20); const charE = font.chars['E'.charCodeAt(0)]; - expect(charE).to.be.undefined; - done(); + expect(charE).toBeUndefined(); }); - it('should properly register bitmap font NESTED into spritesheet', function (done) + it('should properly register SCALED bitmap font', async () => { - const baseTexture = new BaseTexture(this.atlasImage); - const spritesheet = new Spritesheet(baseTexture, this.atlasJSON); + const font = await loader.load(`${serverPath}font@0.5x.fnt`); - spritesheet.parse(() => - { - const fontTexture = Texture.from('resources/font.png'); - const font = BitmapFont.install(this.fontXML, fontTexture); - const fontX = 158; // bare value from spritesheet frame - const fontY = 2; // bare value from spritesheet frame - - expect(font).to.be.an('object'); - expect(BitmapFont.available.font).to.equal(font); - expect(font).to.have.property('chars'); - const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.atlasImage); - expect(charA.texture.frame.x).to.equal(fontX + 2); - expect(charA.texture.frame.y).to.equal(fontY + 2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); - const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.atlasImage); - expect(charB.texture.frame.x).to.equal(fontX + 2); - expect(charB.texture.frame.y).to.equal(fontY + 24); - expect(charB.texture.frame.width).to.equal(15); - expect(charB.texture.frame.height).to.equal(20); - const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.atlasImage); - expect(charC.texture.frame.x).to.equal(fontX + 23); - expect(charC.texture.frame.y).to.equal(fontY + 2); - expect(charC.texture.frame.width).to.equal(18); - expect(charC.texture.frame.height).to.equal(20); - const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.atlasImage); - expect(charD.texture.frame.x).to.equal(fontX + 19); - expect(charD.texture.frame.y).to.equal(fontY + 24); - expect(charD.texture.frame.width).to.equal(17); - expect(charD.texture.frame.height).to.equal(20); - const charE = font.chars['E'.charCodeAt(0)]; - - expect(charE).to.be.undefined; - done(); - }); + expect(font).toBeObject(); + expect(BitmapFont.available.font).toEqual(font); + expect(font).toHaveProperty('chars'); + const charA = font.chars['A'.charCodeAt(0)]; + const charATexture = charA.texture as Texture; + + expect(charA).toBeDefined(); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}font@0.5x.png`); + expect(charATexture.frame.x).toEqual(4); // 2 / 0.5 + expect(charATexture.frame.y).toEqual(4); // 2 / 0.5 + expect(charATexture.frame.width).toEqual(38); // 19 / 0.5 + expect(charATexture.frame.height).toEqual(40); // 20 / 0.5 + const charB = font.chars['B'.charCodeAt(0)]; + const charBTexture = charB.texture as Texture; + + expect(charB).toBeDefined(); + expect(charBTexture.baseTexture.resource.src).toEqual(`${serverPath}font@0.5x.png`); + expect(charBTexture.frame.x).toEqual(4); // 2 / 0.5 + expect(charBTexture.frame.y).toEqual(48); // 24 / 0.5 + expect(charBTexture.frame.width).toEqual(30); // 15 / 0.5 + expect(charBTexture.frame.height).toEqual(40); // 20 / 0.5 + const charC = font.chars['C'.charCodeAt(0)]; + const charCTexture = charC.texture as Texture; + + expect(charC).toBeDefined(); + expect(charCTexture.baseTexture.resource.src).toEqual(`${serverPath}font@0.5x.png`); + expect(charCTexture.frame.x).toEqual(46); // 23 / 0.5 + expect(charCTexture.frame.y).toEqual(4); // 2 / 0.5 + expect(charCTexture.frame.width).toEqual(36); // 18 / 0.5 + expect(charCTexture.frame.height).toEqual(40); // 20 / 0.5 + const charD = font.chars['D'.charCodeAt(0)]; + const charDTexture = charD.texture as Texture; + + expect(charD).toBeDefined(); + expect(charDTexture.baseTexture.resource.src).toEqual(`${serverPath}font@0.5x.png`); + expect(charDTexture.frame.x).toEqual(38); // 19 / 0.5 + expect(charDTexture.frame.y).toEqual(48); // 24 / 0.5 + expect(charDTexture.frame.width).toEqual(34); // 17 / 0.5 + expect(charDTexture.frame.height).toEqual(40); // 20 / 0.5 + const charE = font.chars['E'.charCodeAt(0)]; + + expect(charE).toBeUndefined(); }); - it('should properly register bitmap font NESTED into SCALED spritesheet', function (done) + it('should properly register bitmap font having more than one texture', async () => { - const baseTexture = new BaseTexture(this.atlasScaledImage); - const spritesheet = new Spritesheet(baseTexture, this.atlasScaledJSON); + const font = await loader.load(`${serverPath}split_font.fnt`) as BitmapFont; - spritesheet.resolution = 1; + expect(font).toBeObject(); + expect(BitmapFont.available.split_font).toEqual(font); + expect(font).toHaveProperty('chars'); + const charA = font.chars['A'.charCodeAt(0)]; + const charATexture = charA.texture as Texture; - spritesheet.parse(() => - { - const fontTexture = Texture.from('resources/font.png'); - const font = BitmapFont.install(this.fontXML, fontTexture); - const fontX = 158; // bare value from spritesheet frame - const fontY = 2; // bare value from spritesheet frame - - expect(font).to.be.an('object'); - expect(BitmapFont.available.font).to.equal(font); - expect(font).to.have.property('chars'); - const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.atlasScaledImage); - expect(charA.texture.frame.x).to.equal(fontX + 2); - expect(charA.texture.frame.y).to.equal(fontY + 2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); - const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.atlasScaledImage); - expect(charB.texture.frame.x).to.equal(fontX + 2); - expect(charB.texture.frame.y).to.equal(fontY + 24); - expect(charB.texture.frame.width).to.equal(15); - expect(charB.texture.frame.height).to.equal(20); - const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.atlasScaledImage); - expect(charC.texture.frame.x).to.equal(fontX + 23); - expect(charC.texture.frame.y).to.equal(fontY + 2); - expect(charC.texture.frame.width).to.equal(18); - expect(charC.texture.frame.height).to.equal(20); - const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.atlasScaledImage); - expect(charD.texture.frame.x).to.equal(fontX + 19); - expect(charD.texture.frame.y).to.equal(fontY + 24); - expect(charD.texture.frame.width).to.equal(17); - expect(charD.texture.frame.height).to.equal(20); - const charE = font.chars['E'.charCodeAt(0)]; - - expect(charE).to.be.undefined; - done(); - }); - }); + expect(charA).toBeDefined(); + let src = charATexture.baseTexture.resource.src; - it('should properly register bitmap font having more than one texture', function (done) - { - const loader = new Loader(); + src = src.substring(src.length - 17); + expect(src).toEqual('split_font_ab.png'); + expect(charATexture.frame.x).toEqual(2); + expect(charATexture.frame.y).toEqual(2); + expect(charATexture.frame.width).toEqual(19); + expect(charATexture.frame.height).toEqual(20); + const charB = font.chars['B'.charCodeAt(0)]; + const charBTexture = charB.texture as Texture; - loader.use(BitmapFontLoader.use); - loader.add(path.join(this.resources, 'split_font.fnt')); - loader.load(() => - { - const font = BitmapFont.available.split_font; - - expect(font).to.be.an('object'); - expect(BitmapFont.available.split_font).to.equal(font); - expect(font).to.have.property('chars'); - const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - let src = charA.texture.baseTexture.resource.url; - - src = src.substring(src.length - 17); - expect(src).to.equal('split_font_ab.png'); - expect(charA.texture.frame.x).to.equal(2); - expect(charA.texture.frame.y).to.equal(2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); - const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - src = charB.texture.baseTexture.resource.url; - - src = src.substring(src.length - 17); - expect(src).to.equal('split_font_ab.png'); - expect(charB.texture.frame.x).to.equal(2); - expect(charB.texture.frame.y).to.equal(24); - expect(charB.texture.frame.width).to.equal(15); - expect(charB.texture.frame.height).to.equal(20); - const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - src = charC.texture.baseTexture.resource.url; - - src = src.substring(src.length - 17); - expect(src).to.equal('split_font_cd.png'); - expect(charC.texture.frame.x).to.equal(2); - expect(charC.texture.frame.y).to.equal(2); - expect(charC.texture.frame.width).to.equal(18); - expect(charC.texture.frame.height).to.equal(20); - const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - src = charD.texture.baseTexture.resource.url; - - src = src.substring(src.length - 17); - expect(src).to.equal('split_font_cd.png'); - expect(charD.texture.frame.x).to.equal(2); - expect(charD.texture.frame.y).to.equal(24); - expect(charD.texture.frame.width).to.equal(17); - expect(charD.texture.frame.height).to.equal(20); - const charE = font.chars['E'.charCodeAt(0)]; - - expect(charE).to.be.undefined; - done(); - }); - }); + expect(charB).toBeDefined(); + src = charBTexture.baseTexture.resource.src; - it('should split fonts if page IDs are in chronological order', function (done) - { - const loader = new Loader(); + src = src.substring(src.length - 17); + expect(src).toEqual('split_font_ab.png'); + expect(charBTexture.frame.x).toEqual(2); + expect(charBTexture.frame.y).toEqual(24); + expect(charBTexture.frame.width).toEqual(15); + expect(charBTexture.frame.height).toEqual(20); + const charC = font.chars['C'.charCodeAt(0)]; + const charCTexture = charC.texture as Texture; - loader.use(BitmapFontLoader.use); - loader.add(path.join(this.resources, 'split_font2.fnt')); - loader.load(() => - { - const page0 = path.join(this.resources, 'split_font_ab.png').replace(/\\/g, '/'); - const page1 = path.join(this.resources, 'split_font_cd.png').replace(/\\/g, '/'); + expect(charC).toBeDefined(); + src = charCTexture.baseTexture.resource.src; - expect(loader.resources[page0].metadata.pageFile).to.equal('split_font_ab.png'); - expect(loader.resources[page1].metadata.pageFile).to.equal('split_font_cd.png'); + src = src.substring(src.length - 17); + expect(src).toEqual('split_font_cd.png'); + expect(charCTexture.frame.x).toEqual(2); + expect(charCTexture.frame.y).toEqual(2); + expect(charCTexture.frame.width).toEqual(18); + expect(charCTexture.frame.height).toEqual(20); + const charD = font.chars['D'.charCodeAt(0)]; + const charDTexture = charD.texture as Texture; - const font = BitmapFont.available.split_font2; - const charA = font.chars['A'.charCodeAt(0)]; - const charC = font.chars['C'.charCodeAt(0)]; + expect(charD).toBeDefined(); + src = charDTexture.baseTexture.resource.src; - expect(charA.page).to.equal(0); - expect(charC.page).to.equal(1); - expect(charA.texture.baseTexture.resource.url).to.equal(page0); - expect(charC.texture.baseTexture.resource.url).to.equal(page1); + src = src.substring(src.length - 17); + expect(src).toEqual('split_font_cd.png'); + expect(charDTexture.frame.x).toEqual(2); + expect(charDTexture.frame.y).toEqual(24); + expect(charDTexture.frame.width).toEqual(17); + expect(charDTexture.frame.height).toEqual(20); + const charE = font.chars['E'.charCodeAt(0)]; - done(); - }); + expect(charE).toBeUndefined(); }); - it('should register bitmap font with side-loaded image', function (done) + it('should split fonts if page IDs are in chronological order', async () => { - const loader = new Loader(); - const imagePath = path.join(this.resources, 'font.png'); - const fontPath = path.join(this.resources, 'font.fnt'); + const font = await loader.load(`${serverPath}split_font2.fnt`); - loader.add('image', imagePath); - loader.add('font', fontPath); - loader.load(() => - { - expect(Object.values(loader.resources).length).to.equal(2); - expect(loader.resources.image.url).to.equal(imagePath); - expect(loader.resources.font.url).to.equal(fontPath); + const charA = font.chars['A'.charCodeAt(0)]; + const charC = font.chars['C'.charCodeAt(0)]; + const charATexture = charA.texture as Texture; + const charCTexture = charC.texture as Texture; - done(); - }); + expect(charA.page).toEqual(0); + expect(charC.page).toEqual(1); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}split_font_ab.png`); + expect(charCTexture.baseTexture.resource.src).toEqual(`${serverPath}split_font_cd.png`); }); - it('should load and uninstall font cleanly, remove all textures', function (done) + it('should set the texture to NPM on SDF fonts', async () => { - const loader = new Loader(); - const fontPath = path.join(this.resources, 'font.fnt'); - const textureCount = Object.keys(TextureCache).length; + const sdfFont = await loader.load(`${serverPath}sdf.fnt`); + const msdfFont = await loader.load(`${serverPath}msdf.fnt`); + const regularFont = await loader.load(`${serverPath}font-text.fnt`); - expect(BitmapFont.available.font).to.be.undefined; - - loader.use(BitmapFontLoader.use); - loader.add('font', fontPath); - loader.load(() => - { - expect(BitmapFont.available.font).to.not.be.undefined; - BitmapFont.uninstall('font'); - expect(BitmapFont.available.font).to.be.undefined; - expect(Object.keys(TextureCache).length - textureCount).equals(0); - - done(); - }); + expect(sdfFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).toEqual(0); + expect(msdfFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).toEqual(0); + expect(regularFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).not.toEqual(0); }); - it('should load and uninstall font cleanly, preserve textures', function () + it('should set the distanceFieldType correctly', async () => { - const textureCount = Object.keys(TextureCache).length; - const texture = Texture.from(this.fontImage); - const fontText = BitmapFont.install(this.fontText, texture); - - expect(BitmapFont.available.fontText).equals(fontText); - - BitmapFont.uninstall('fontText'); - - expect(BitmapFont.available.fontText).to.be.undefined; - expect(Object.keys(TextureCache).length - textureCount).equals(1); + const sdfFont = await loader.load(`${serverPath}sdf.fnt`); + const msdfFont = await loader.load(`${serverPath}msdf.fnt`); + const regularFont = await loader.load(`${serverPath}font-text.fnt`); - texture.destroy(true); + expect(sdfFont.distanceFieldType).toEqual('sdf'); + expect(msdfFont.distanceFieldType).toEqual('msdf'); + expect(regularFont.distanceFieldType).toEqual('none'); }); - it('should properly register bitmap font based on text format', function (done) + it('should properly register bitmap font with random placed arguments into info tag', async () => { - const texture = Texture.from(this.fontImage); - const font = BitmapFont.install(this.fontText, texture); + const font = await loader.load(`${serverPath}font-random-args.fnt`); - expect(font).to.be.an('object'); - expect(BitmapFont.available.fontText).to.equal(font); - expect(font).to.have.property('chars'); + expect(font).toBeObject(); + expect(BitmapFont.available.font).toEqual(font); + expect(font).toHaveProperty('chars'); const charA = font.chars['A'.charCodeAt(0)]; - - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charA.texture.frame.x).to.equal(2); - expect(charA.texture.frame.y).to.equal(2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); - const charB = font.chars['B'.charCodeAt(0)]; - - expect(charB).to.exist; - expect(charB.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charB.texture.frame.x).to.equal(2); - expect(charB.texture.frame.y).to.equal(24); - expect(charB.texture.frame.width).to.equal(15); - expect(charB.texture.frame.height).to.equal(20); - const charC = font.chars['C'.charCodeAt(0)]; - - expect(charC).to.exist; - expect(charC.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charC.texture.frame.x).to.equal(23); - expect(charC.texture.frame.y).to.equal(2); - expect(charC.texture.frame.width).to.equal(18); - expect(charC.texture.frame.height).to.equal(20); - const charD = font.chars['D'.charCodeAt(0)]; - - expect(charD).to.exist; - expect(charD.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charD.texture.frame.x).to.equal(19); - expect(charD.texture.frame.y).to.equal(24); - expect(charD.texture.frame.width).to.equal(17); - expect(charD.texture.frame.height).to.equal(20); - const charE = font.chars['E'.charCodeAt(0)]; - - expect(charE).to.be.undefined; - done(); + const charATexture = charA.texture as Texture; + + expect(charA).toBeDefined(); + expect(charATexture.baseTexture.resource.src).toEqual(`${serverPath}font.png`); + expect(charATexture.frame.x).toEqual(2); + expect(charATexture.frame.y).toEqual(2); + expect(charATexture.frame.width).toEqual(19); + expect(charATexture.frame.height).toEqual(20); }); - it('should set the texture to NPM on SDF fonts', function (done) + it('should unload a bitmap font', async () => { - const sdfTexture = Texture.from(this.sdfImage); - const msdfTexture = Texture.from(this.msdfImage); - const regularTexture = Texture.from(this.fontImage); - const sdfFont = BitmapFont.install(this.sdfXML, sdfTexture); - const msdfFont = BitmapFont.install(this.msdfXML, msdfTexture); - const regularFont = BitmapFont.install(this.fontText, regularTexture); - - expect(sdfFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).to.equal(0); - expect(msdfFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).to.equal(0); - expect(regularFont.chars['A'.charCodeAt(0)].texture.baseTexture.alphaMode).to.not.equal(0); - - done(); - }); + const loader = new Loader(); - it('should set the distanceFieldType correctly', function (done) - { - const sdfTexture = Texture.from(this.sdfImage); - const msdfTexture = Texture.from(this.msdfImage); - const regularTexture = Texture.from(this.fontImage); - const sdfFont = BitmapFont.install(this.sdfXML, sdfTexture); - const msdfFont = BitmapFont.install(this.msdfXML, msdfTexture); - const regularFont = BitmapFont.install(this.fontText, regularTexture); - - expect(sdfFont.distanceFieldType).to.equal('sdf'); - expect(msdfFont.distanceFieldType).to.equal('msdf'); - expect(regularFont.distanceFieldType).to.equal('none'); - - done(); - }); + loader['_parsers'].push(loadTextures, loadBitmapFont); - it('should properly register bitmap font with random placed arguments into info tag', function (done) - { - const texture = Texture.from(this.fontImage); - const font = BitmapFont.install(this.fontRandomArgs, texture); + const bitmapFont: BitmapFont = await loader.load(`${serverPath}desyrel.xml`); - expect(font).to.be.an('object'); - expect(BitmapFont.available.font).to.equal(font); - expect(font).to.have.property('chars'); - const charA = font.chars['A'.charCodeAt(0)]; + expect(bitmapFont).toBeInstanceOf(BitmapFont); - expect(charA).to.exist; - expect(charA.texture.baseTexture.resource.source).to.equal(this.fontImage); - expect(charA.texture.frame.x).to.equal(2); - expect(charA.texture.frame.y).to.equal(2); - expect(charA.texture.frame.width).to.equal(19); - expect(charA.texture.frame.height).to.equal(20); + await loader.unload(`${serverPath}desyrel.xml`); - done(); + expect(bitmapFont.pageTextures).toBe(null); }); }); diff --git a/packages/text-bitmap/test/BitmapText.tests.ts b/packages/text-bitmap/test/BitmapText.tests.ts index 14721dc640b..0366048905b 100644 --- a/packages/text-bitmap/test/BitmapText.tests.ts +++ b/packages/text-bitmap/test/BitmapText.tests.ts @@ -1,27 +1,35 @@ import path from 'path'; import fs from 'fs'; import { BitmapText, BitmapFont } from '@pixi/text-bitmap'; -import { Texture } from '@pixi/core'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { settings, Texture, Renderer } from '@pixi/core'; -describe('BitmapText', function () +import type { Container } from '@pixi/display'; + +describe('BitmapText', () => { - before(function (done) + let resources: string; + let fontXML: XMLDocument; + let fontImage: HTMLImageElement; + let font: BitmapFont; + let font2: BitmapFont; + let font2XML: XMLDocument; + let texture: Texture; + + beforeAll((done) => { - this.fontXML = null; - this.fontImage = null; - this.font = null; + fontXML = null; + fontImage = null; + font = null; - const resolveURL = (url) => path.resolve(this.resources, url); - const loadXML = (url) => new Promise((resolve) => + const resolveURL = (url: string) => path.resolve(resources, url); + const loadXML = (url: string) => new Promise((resolve) => fs.readFile(resolveURL(url), 'utf8', (err, data) => { - expect(err).to.be.null; + expect(err).toBeNull(); resolve((new window.DOMParser()).parseFromString(data, 'text/xml')); })); - const loadImage = (url) => new Promise((resolve) => + const loadImage = (url: string) => new Promise((resolve) => { const image = new Image(); @@ -29,46 +37,46 @@ describe('BitmapText', function () image.src = resolveURL(url); }); - this.resources = path.join(__dirname, 'resources'); + resources = path.join(__dirname, 'resources'); Promise.all([ loadXML('font.fnt'), loadXML('font-no-page.fnt'), loadImage('font.png'), ]).then(([ - fontXML, - font2XML, - fontImage, + _fontXML, + _font2XML, + _fontImage, ]) => { - this.fontXML = fontXML; - this.font2XML = font2XML; - this.fontImage = fontImage; + fontXML = _fontXML; + font2XML = _font2XML; + fontImage = _fontImage; done(); }); }); - after(function () + afterAll(() => { - BitmapFont.uninstall(this.font.font); - BitmapFont.uninstall(this.font2.font); - this.texture.destroy(true); - this.texture = null; - this.font = null; - this.font2 = null; + BitmapFont.uninstall(font.font); + BitmapFont.uninstall(font2.font); + texture.destroy(true); + texture = null; + font = null; + font2 = null; }); - it('should register fonts from preloaded images', function () + it('should register fonts from preloaded images', () => { - this.texture = Texture.from(this.fontImage); - this.font = BitmapFont.install(this.fontXML, this.texture); - this.font2 = BitmapFont.install(this.font2XML, this.texture); - expect(this.font).instanceof(BitmapFont); - expect(this.font2).instanceof(BitmapFont); - expect(BitmapFont.available[this.font.font]).to.equal(this.font); - expect(BitmapFont.available[this.font2.font]).to.equal(this.font2); + texture = Texture.from(fontImage); + font = BitmapFont.install(fontXML, texture); + font2 = BitmapFont.install(font2XML, texture); + expect(font).toBeInstanceOf(BitmapFont); + expect(font2).toBeInstanceOf(BitmapFont); + expect(BitmapFont.available[font.font]).toEqual(font); + expect(BitmapFont.available[font2.font]).toEqual(font2); }); - it('should have correct children when modified', function () + it('should have correct children when modified', () => { BitmapFont.from('testFont', { fill: '#333333', @@ -79,51 +87,51 @@ describe('BitmapText', function () fontName: 'testFont', }); - const listener = sinon.spy(text, 'addChild'); + const listener = jest.spyOn(text, 'addChild'); text.updateText(); - expect(listener.callCount).to.equal(1); - expect(text.children.length).to.equal(1); + expect(listener.mock.calls).toHaveLength(1); + expect(text.children.length).toEqual(1); text.updateText(); - expect(listener.callCount).to.equal(1); - expect(text.children.length).to.equal(1); + expect(listener.mock.calls).toHaveLength(1); + expect(text.children.length).toEqual(1); text.text = 'hiya'; text.updateText(); - expect(listener.callCount).to.equal(1); - expect(text.children.length).to.equal(1); + expect(listener.mock.calls).toHaveLength(1); + expect(text.children.length).toEqual(1); }); - it('should render text even if there are unsupported characters', function () + it('should render text even if there are unsupported characters', () => { const text = new BitmapText('ABCDEFG', { - fontName: this.font.font, + fontName: font.font, }); text.updateText(); - expect(text._activePagesMeshData[0].total).to.equal(4); + expect(text['_activePagesMeshData'][0].total).toEqual(4); }); - it('should support font without page reference', function () + it('should support font without page reference', () => { const text = new BitmapText('A', { - fontName: this.font2.font, + fontName: font2.font, }); text.updateText(); - expect(text.children[0].width).to.equal(19); - expect(text.children[0].height).to.equal(20); + expect((text.children[0] as Container).width).toEqual(19); + expect((text.children[0] as Container).height).toEqual(20); }); - it('should break line on space', function () + it('should break line on space', () => { const bmpText = new BitmapText('', { - fontName: this.font.font, - size: 24, + fontName: font.font, + fontSize: 24, }); bmpText.updateText(); @@ -132,19 +140,19 @@ describe('BitmapText', function () bmpText.text = 'A A A A A A A '; bmpText.updateText(); - expect(bmpText.textWidth).to.be.at.most(bmpText.maxWidth); + expect(bmpText.textWidth).toBeLessThanOrEqual(bmpText.maxWidth); bmpText.maxWidth = 40; bmpText.text = 'A A A A A A A'; bmpText.updateText(); - expect(bmpText.textWidth).to.be.at.most(bmpText.maxWidth); + expect(bmpText.textWidth).toBeLessThanOrEqual(bmpText.maxWidth); }); - it('letterSpacing should add extra space between characters', function () + it('letterSpacing should add extra space between characters', () => { const text = 'ABCD zz DCBA'; const bmpText = new BitmapText(text, { - fontName: this.font.font, + fontName: font.font, }); bmpText.updateText(); @@ -164,25 +172,72 @@ describe('BitmapText', function () for (let char = 1; char < renderedChars; ++char) { - expect(bmpText.children[char].x).to.equal(prevPos + space + positions[char] - positions[char - 1]); + expect(bmpText.children[char].x).toEqual(prevPos + space + positions[char] - positions[char - 1]); prevPos = bmpText.children[char].x; } } }); - it('should not crash if text is undefined', function () + it('should not crash if text is undefined', () => { let text = new BitmapText(undefined, { - fontName: this.font.font, + fontName: font.font, }); - expect(() => text.updateText()).to.not.throw(); + expect(() => text.updateText()).not.toThrowError(); text = new BitmapText('not undefined', { - fontName: this.font.font, + fontName: font.font, }); text.text = undefined; - expect(() => text.updateText()).to.not.throw(); + expect(() => text.updateText()).not.toThrowError(); + }); + + it('should set the text resolution to match the resolution setting when constructed time', () => + { + const text = new BitmapText('foo', { + fontName: font.font, + }); + + expect(text.resolution).toEqual(settings.RESOLUTION); + }); + + it('should update the text resolution to match the renderer resolution when being rendered to screen', () => + { + const text = new BitmapText('foo', { + fontName: font.font, + }); + + expect(text.resolution).toEqual(settings.RESOLUTION); + + const renderer = new Renderer({ resolution: 2 }); + + expect(renderer.resolution).toEqual(2); + + renderer.render(text); + + expect(text.resolution).toEqual(renderer.resolution); + + renderer.destroy(); + }); + + it('should use any manually set text resolution over the renderer resolution', () => + { + const text = new BitmapText('foo', { + fontName: font.font, + }); + + text.resolution = 3; + + expect(text.resolution).toEqual(3); + + const renderer = new Renderer({ resolution: 2 }); + + renderer.render(text); + + expect(text.resolution).toEqual(3); + + renderer.destroy(); }); }); diff --git a/packages/text-bitmap/test/resources/bmtxt-test.png b/packages/text-bitmap/test/resources/bmGlyph-test.png similarity index 100% rename from packages/text-bitmap/test/resources/bmtxt-test.png rename to packages/text-bitmap/test/resources/bmGlyph-test.png diff --git a/packages/text-bitmap/test/resources/desyrel.png b/packages/text-bitmap/test/resources/desyrel.png new file mode 100755 index 0000000000000000000000000000000000000000..c3559e1c80629bfba14ba0839120cd46950552ed GIT binary patch literal 310362 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

D_HoE?I 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%0A5SHfZQ`ci?KI%+PsdR# zbpFMDwB{$Em4k4b+S;G7IM5#c*GumnqT?^t2muC+aO`{a`Qt@lb$Dvn&|$?;O`J9B zi^~P*l|2E|egRlbk{z5?Boax8v<<+3(*Zod%oofx$QPgU1;k1F`+;k6S}M<-mVDEj zJ6rXy{Cvv=|9#*L6@IAA3P>0YF%M=Sd5(9mI&js96vwWl#P}AZB`aR;R0dKNxV;*k zl1T5N=0E1er#eU)GeEkPu4Egv2nI*JxxegxnFlWAm32I-;u=G?jw~Y@yhpIT3`mW8 zz%-6=ISqH+Nqn)}8J@x&Ye3e_LM`ARDEyP8(sPE=P#|HJ=@5s{9hxOpRiNeE_Yw2c zFl&1i74RpulKG{F1_VHW9z)y4-%t|;CyT* zP>>W*!<{R>QTUsJznO6!=SARzjDe|I1y&lB)eDCyXU|E4ECIZv!o{{EvraW64%nD1 z^!T%hOW4{MFfSS*=Kyc2L7rRbL#9?Wiz@;^Y(+e1JiH8kmP8@f}BsMman?Y>sHkq58&Fo|Tw@G4Tlk z@D+z{^EAvtU;4=R#;Rw}#IX&9#*or(Bi5_BDJ;JISeY?;s9T2sC>MZ5=yC;yh!oNB z(_8&mY!DPUTzU>x`li45>tza6!RhP=_=I|%Ca%42i;)Z$_EU#>=((0ArZ?+~zRTa# zA_e~d&q?dmsk+Z?-c|Y2qZKV;L?({zER@{-%~{IJ9~8%IIO6}x;_>l2rg=miaM7!V zSEoEb)5l&XZj4i{Sml@)AqEkM9}keq09FTOdsPU$TSKdS{kdM)fLP5215HiUOGj%r zqJwYy-ov|Ov)V0dcjRkUq(dt}gS4$NJtoS?xF$z*7ArpGdSLgFNkc>=a*{d&pIf0d z!eJ36P~k*LZ+0pUKTRmh2>rh_aYw^uk(HArm}SMsI1Ox&qEHmHg9qP$M<-C_7)}^0 z@{paIGdzg~@8lMGYR{Qs6_{G9x6u>0U$(VLP z_u=U0x#e>*fAT+HoizTn2bVgIynK=R&z~<)pn@dTgjjC|37~wCKh2B887DKdNDe4= ze7xf8Mj-qsT(fZJ+OJ(D;ty(oA)23meZ??xbC9o9DcnO~5`R?a71_xy8o+_oL{aZ_ zX+E%4Z92~yk(nT;H5&)4oeypuPC|x}!*Cwvk!7 zjW^OB7Xb)X8}2;ZB+mH(=Hy^Fyecm)1QvZ6Nb?hrNA_+-?!aYqUoXaXpEPzQ2m>xYk$Qg`ENZK`lQ{_H;xA2U5cH2>F~7ZOW(L> zs=8v<5ZNC=(Xt+P8#Q`0arJMH8E}}Woso<4cx=+qfSWN8><|G5xhMVFAc5OtEMGW4vT%r>_@jgw$rGn^=nJU#&Flp#o9J-VYh?=`Z3Vjsrd9L#CWmi(PwDL z)odeTHvwFLC+}FK9&OO(Z8+?^Mkt9xp^kkzg|S)eDTQ7+0LZbq5rQ=&J~`5}2oNC+ zDNyo17@?IW%xS8jevzad(coCzDPbVJZd|JNjosyK1+T8Jj=JbfxC+HgAc+rkT9gM@ zkeG8y8?`05DN(!iwD>BdEgur#`G2sbuvV-1|p7d2t4PO6B~pp@#Hh~aFE^- z<;VVCBGl062y(Q0dcUTNonx~qbL#sj*l2NG#WO{VS|z6!$F5T zT%_dvI4ouz?FA2Mks%11Zf|U?7Sl(^iBaiM5`X3w`Ps}5=jj~uH6!9Z(d1~wKCL(O zk;|~F%ew09EWimU*=T4#Oi^OPKCEa_U7Y1Zl}~BFmcCx|^O(zT(|K}gG6oPEp%$c# zt?gn|oHK-mZ$X+SE$nJP5jz$cJ)U1sb;J6dRpQL4@E3zTy5P!w0oY!6|CspUqdSbT zX)bMUPINn9F9q(mfY-1N(uCVW!dD(%FWNrDEoSHlE&*QkYQ=IahV;^u7Sc3iX z(D{KzXz<9RQMC;Q*jyr1u&H<3_DGwK6V~6N`+fP^mD%FvOR^QIG$!e!6If`YlB#xb z^~1$n{fEz<7!SvqN+~B~MOQa!p-|BtM_XT{@jEg_+1KHC=zm{$;2dS_h(vJOC_ci4 zlOq29cCq;Phh@fjQ(_@M1@4b9c7S*{D521SLn6=uB}jXL+L7PM9)K&@Nmg$E)608a zyXneliY@rfbc<(ZiU0e_eC5UmHhrVX?{h95A%405maC_VQ8=&JkMkO^Sx9>~?0Xf$3%9y2-Zf2(%Af%m=3vHQR(wW?Kz|~nMpO-xqb!0iKg)nV6_0-N z^evZ##`K(HQYn(Zn{|K~B{9Sfj60MD2ys;%}<;hF`8|ja*Sz@1Iyx3p2n{ z`&m)oRWO{9=mHDes6#Quc)uHx>btNgI|Rjts^Un%OG9PIQ-Xr;{R+Tu77~nFF)s@! zvT8*7!N2^Sjg+m3#JE*2vWE>3tx40p{n{b-1sDr<&Yls#LxDWfYOnP{JZ`sd#PQ?3 zc{y>;d#@j>Ov&N#5c`JN2Y6>a@Jnnt=o8<5wAe_Gcjybp#)m*JrHHr*HO>#KVozNY zOrjTkS^$)=^b}D3mEb%+_2-{2Qx;6a(GbeD!-w0d#7};|-GI=ao*L(BK>3B(5Wsw_ zzPrr{m+4s4*m3)N$1&jBTb;_b@BiwD+Zy)2@B$-@D#fG;^4^Y{fVvVO|oo$78cytzbSej=9q}f8&Zc zvf>~vlY_=Dihvb7@z$m)@%($`#>T=%k&YeZ%;8aDeUYF2Q7)!s_Ds(VWF}^=IGZqn zCx+dE==9vsmlPO{d3j_;blkUAj{t1IFjhotd*Y}VJG%T`t>VJz2^dh7It;Q$(X5S? zUHelg5X9jj$VAeNRmZHMal-3u1+~z_ozQwS{fczPwWE|fU#bkJuKNDlSD!mSTbw;F zOTp2XD644`Z*M9$w(M&VBZs)d7fnxq#HQMSB!>ahW=&`x!*u>0r7lqS2964umyInx zql%$xBF#0)*~uRaO>~x{UU`U+3z$;S4AFQ7{TPtIhn51(#zw^9b|X>|QQKPK=9c+c zlx*kP@B3w=vf_;KBN7x%<1i!}AH^Hutu6INb`nU$5G{bTN>`1RdjF|UUVVX#IO#1O z@D+>i-^H%_ZfroI@LWw6U8*ya-440$7|ML&GFI6r+3r&Tx@lJl*SKK77x_iAbBRh)n z1@y?cAAcXiG1E4O>aBQjLsuHGvh4FMAB)CRL%Zsuf{HzVd~uKK+m}v~eL*4(^XoyIR9Z?TaauD;f>&j9r^;>i{OO)WTQCdJ7BoC09^ zD;*y9{Ju8mB8w>W}Qp_Mkj(n3;{TKlO#dtIaq;0BwLvE!H7!>5viD%;zY~9 z{Z3;y>w>Wo0D_V%LS&gC%V!cwcc4@^EXz7iReJ(5LNFC-E?n(0?DAkGOliS(1a*?; zO9#o3Mpwj|zclQmBt4kb#Lx&*k&`dbPE_Nk;mfk(c}% zz)0$XTE+LjHbasO zE5~}Wjtrfj%{TI`q%Tq#YtOi(Ihv{dcxR1xd0n~jHq?-?0MSMbaf*v)Bm|+;4X%?> zx8X=&vYCU4Qx+hPMr3)Ns&l-s&-4lX0{N66;fMY-w|&uw$hFko0z3K#cYwYH-oeDU1) zA3@rB)2@BhH+-_YdMuU|4q6{fk5|=;rzHg8Yzyb)Mm0b?2za*f53I4nK7XL`MWjbl zOU!mIiSJOK;N`JR)ljwc#p=c}NIIoBpwkU=zHWJ%<51i6FoYW;p}H2~Z}Aj};9w2r z;2hqtW_d0bLXrr0V`%k9#P-9jV%6k$dhTf;cLisFE&Y{{H**{K6*w9VdbkmSsozUU zbUS~zW{i62;tYBzG$((;ZDSXeARRa12<3-Q6d9W!$hd5LtUe;e)r=@d5OWh4EX;a?7I0jK@#gtQZ(FK<<-7?fhfE|Cji#-_>gdv2KhQ@cIkc%G;7`y{ zituFvELUyvYg&oebjmUs9UzfjmO_|tXN>-xpFXnjPb0J96>@K6u-XpR0mUD0ouk}v z=@{|b=MOA>LLH}7x;ZGVIu(tIrtHS^Cx$_<(pz4g<`kqA{(AT zwyK4=0(4-klyP?Gf_HSot-++ysg?s4|C<|k*T5hbXBq}sl58XDKjWa706^hN-eru_ zaKQqAK*!1AqbjSvH))2{xhZpfZL8yOS0GGDCDD9ELT(QwJDj zuvkK4!p1XpOj>LSuK4s&z(QCLWsrsY^{L{K56hgbKmWtVhhKc>pzFui&Q{J_lp`$) z+WZYOGda~GGg%Q?A}2#yPotfN&3o&`+D|IOlmlUM2$rOM+KRzU_cfBV;Gc}G9tIqu`p9>=%-dFO03duR*>S{R~}KuU~? z4SQR~n_HW(`;P}Ij2a-~AXWus5x1Ap>YafvD=EhYmTy=$a}6P`TsdC+>Q9@a57z|8 zj!sMZGur?FAOJ~3K~#4^hagD`O(A0Ev>nyvggZ;~woXltecdrE>IhgmbI`ijt;2sj zIMl(Fb4j)_T{)t~`D&pp*JXk9}C zInRgyF!8rOQFSd6F|$GH6dAi>w+BR9B8*-O;5yuX2E*LN1FNqVmjz}Z9${B z?N3K2>=(uniw=R$dJxJ%wAlvWZ$rBt+Sk|+p!?na?EJqB5`5;jKUu0?dtsh==5L{` z)gKm@{p3B^ zuD$IqKR-)3f8j8ofny>9@c}@mj82r!>1rAR+z4d6zM=ZgJ;lDCMMo*+&=+1a4+~W0 zHCXh-qE8l1HUU-o0ui+xJ53KJ6-ku5qG3m5#3}`a9IJ&#aTqRF{1-zNuzQ7p_-w3F zZ~w-s;c_A(k(!Gc9fDVyD6S4Fi^s)+Y6mBvJZS)cYlFka&!(el| z92QGJ#_9K^q^40G&&l?%Q*%t_c`C$&u?1F~I8RjvV^L%0-|cQK0Iav9b^yT5H`WCl z11RsOU}t8c!Hni~NHtQvvU)2XZ5PuJ8X$S;QijjU_7rYz>{Pk8L{hV8TBnn?XXR!U z+*KGe!6YL4XZQTs0l}hcpFcnP+1k3`u_HB2KfdOUwF{vAg7d{ph2}noCPj;6sKH@U z7rwTTsBQF1_VfOdCZn*Z(Wq{0SIK37Z=q0DqC;Jo7Z*%TaCkw4@C^^?ZNsQS;m3fl zV(fU2V&77MVsE!$0S>y*j{VF2J{WhD>JVm_ei z5I_`aZBP%@_LoJ^{81?X$O8RL0@kcIo;f{JPFd zI(+Jn#6Mu20DNhW+3VfMEIQu-0*e?6=TBEkUElhh4;Ov&+^=7P;@>LPq z+t%W5&c{T19NK|BkyZdt@S5pK559e*)p7M*@BieMuS^lQUNwa~9ode!NjzaV6luv( z;@cPGh;N;jtyVYq#iK7D%l_B8+Whum#tax_I)=PDOzLxE?jwF^(8U)r)b?5ktDa(E ztvFIpX(f*HDeJ?GiT)TI0bpm&QlWGX4!{7m(kFpUvn@r+W+x0NpX^}{T=)f3Sp$N_Y?|6;jz2~Y**WG#OZ3xKH&3jpAWrvMnSG|dyj zwA)LdO4L$Fg=fu*-;|rG{1|img3_kY%A%sG2|M;yCWj-!1zQWyWjA1oUDZ8UP{gQxD-cZ{>b?D#At^PgO3l@p;HrBq@puNSU7`gSWHgk@GVpYpOkgbmBTlv705uu znf;7C?fAgT)*W~Noxl>WxECCf8<89AM5qxQmwbRh|0etfim{$}CS zrr2z2-iYGTnt&)c)G98Sk$`an!hgaz3QwO6b)WRSI69U30EUqe?%cC*T1M;-zB*Zf z`MucRK2vySMV%iuF%reHIhpEGc+$%o84vi-qyUcpWb5Ktk^+9)lpDdg^!Ilv!~@Tl zfWxY4tEa_lSRB%HX))@z9W~pm7?E9iz*%0lv)Py5|DEqwW>3!4Zn$y=&7RBhF$)WL zVHID#^&JBmI+0a*v6|BTuO# zFYNvGTN}&Vzq@6QGJOo}9}q$21$P@?LZl_R#obrsDDUrRbOF`h8|#XC{PH|s8QSAi zRY>~^vW(a30sxh2hSjd{u_~`CH;c|M*oz3hffai^hAfS2I=ITzapDaJG-eG=>g^X8 zgC7}ixv_J3duUSB*gxDdl@^NuyG6JpUi>}r-zp;~#l;n(7j>(LP8->MpBilX2^|nc zRY~&*fP*;$I|l8A!)OwVCVSFLH=YB~;gvf#<{1Y|yUf%Kihv;^XdB3;!d}SXzy{3( z!iq77w=fnO>~}yn>B1xcC|58@^*^lkVePmJH{XRxM@A$anQ0X1CRwJ!D=RBeV=9Zu z*ZsVBz=1KBS}1_P!N3pQ`C^TS1%?3wqd1B|o;K2Y%swB3(h_)_95zqv_c-I5CSxIiOtI5gm+UEyTz#UFNSdIN^1dVGUhSiKJTXaG2k@CXTO zDqeqOScGxpK(?QbNm;_f#*#a~jyA=ML25!sM?RK5B>I{Mf4IaoX>^h(t7>&V@#5~Y z-`QAN80#>u2tY3m_?m^C;CDbgBffj-c=3ZZV-+_>3VWADSWJRa#Qo2e7@PJr>m1-Q zfsw1R6X&o6?IELrXXB_>7aZefyT|R!f9}8g&RRS>o4vv8B3$($)8E~?R5|;M5z1|k ztiP(HqV?<5F^=76ws(M7vh$hOF!ZfOFh(|G^`a53C*iZ6uy9iP()2WS@weZa|K4Hk z8_OoBzmIKb3clD6VKQX%nFrvSs%wwo*f46`xGko*SC%t6ckO0 zflLF8B%!vYL8oZRH>cl0ff-}QpXTE{<+)!j14y9iyrJTfr8%(TOl}X*j&@>Gn$qMnG83`M2N57@s6>5UyZhEN~{K#!w~3JpzCjZ5Ymk8 zK_QL(^!bRPukhIM@-bd`RbTV;5wXwbrZ|eWm-~LP;-+_JoHH*|+;sU^W!AVP?mlGi z;ow7@5`NT&+5#}L9GT}LX>X!2&b`!n71=j`6IigrI}93mGvL zp50X^IG4Gw31`*I4Hke*VoxLdVsaATDGtm7;t#`4Cu-{>MyzO9>m|S>Cpd)1)3x}* z0!H~T7C>ng3xJ>-d+?J407)2dWP_Fc81J#Tp$YX-hF;{-MG8dNhF}nbzXcU+bRCUN zYZ&B>gMFv#ZCGWrsSbxv(G)NbbT19I1VxlzxSK-7AraxEkGxsLr|QX9gq>fG*Wpvq zP6GX>KcgOFkl%GL{N^Hc=EPLVT^Kh!36jdglyBbsp7Z&&MK62Y4t?r~1aaZwk?Ix8 zM~d`hHzp*U_jlWb6Sjw5C^r7|R;6*yq*y)P?WjdN?#9YxV;I)rBJHiMJ?-2H6^`B> ze&#=W&${!w3t&4TRst$12br?&s}_yIUyl0m_Hyyzma-W;57teuZ!$dsBfc^*H%Xa3 zK2;-hRQ-1$wu;44F{+u0!Qf98;Ju(Zv{%WxYDXC(NeTyktJ!KA+v39$1w z3L_!CJkaL#!b)O~f|zFQPkcpL2LRXBH$N)=(#``lV(M6!LWDNbH}8JmShuZ0Ta_21 z#kf=me=6I6v-hB?v_)z2R#~;)eIIrhT<{KLeqi<| z4JTayw1*hcuN3UHzs=nnd%K=&2_ z4X_fdtba`!l^FNeJLW2oNS0@oBv47rXnsG~!9RJbNS~S&1(vM}gZf5^szYKqqBmOu zb8khQ>{~h}U=jj*huJ+in4=TXuL8IYTq(oa9ZHKR1JUP}#DSHqY!3p(c46SzbQr3C z`0YSrINPFij5Fv8M8YWsB&VKlBK{}{#A6N`A;_h09SOtEn$-qN8K210gLEj=6>vOf zgT~ix`eIXGVVP2vpzcGhJbUk&zH@8q<*lp`?0@ zmlVK6nOL$Yk#K;VfWF}a(YRO$0+uk&rM-~xt@MPGUGxW_z+#O{iE{GD1%eB@9tegp z@x!H{H%#LxwDd?*t>pC37|zMd1gc0na?m}F*W;~g*60+kYi8wThG*xcN3lwh7_63g z;*KTC?{8hmV-m2+bjj*x9J%X99Eky|P`c4zvFv%ubuho?=P0bLb_pVkZ5JI;Q7qyS>nuTIJ(2Q3htd5K{gp$ zkuVadjwX~;D6-*&6C1&Jq*wq}Q~l69;YHpwD09lR-%C9P`f2t28CjvPo zj$-Z*Q7z<5oc!&rqcG;7L`DvAaTi^NDi>)+dwt!eUh&&+xG*khkoCfRU=H(U-?ZpY zwuuBtl40lm&VKvq$Ccu-my3;~)qVkkOU7lh5&~F%(@{w&+GigsvJ(xsM-R7`)a!u; za)wT{IP3@DKgD`}?9ywWzu=q&Icia9lX3W1lUND1Kjf^ckxv15knh6`^(R`uS4KZE zAc2!E`ukCSk5NfyXtzkN@HVOQ#DVOD_~wzxQQMl^BMT2!2hV-tl_O(+`HzD!DG4qe z=I9j;mHE4xjN!?y2)x8%z%ybnP`gf}?UpWZpL79$UF#>?_t&jPqm#oU34j-})TfV2 z7PSrDq@1CyBvp6BOlgoRbiH-_E`<-~4$U;Ga+OGM=j9MpruB|<56_B za~jHw2AoG_q&{2_e>u*8AB4q6+PAmPG~_wG0k)+9d@~o&1?tBE96yjhtq;in)jo%A zIB^01=f1~7RFo7bB^8E?oR%h6CS1jI&zv+zyi*O3m3IzJ}aSFnb<6s2b?nbitI zfdZa4^C#jHC4CCWZVobWNcB-kFG!CU9T}UH)Tg|9iIhHWBoxWnR#;##Z}tfWRtLv@ zvcJf|pC8!(xHFD~1D9r~quucE4r5bclg^z#G+JQi9BNEBV@0l?v}?Xn%eYQ&bvGP_ z_O%bUmhQaqm+wdY9tM|W{wxq>$?|a}Ohh67@w=HJe#v*ljh%{L*tZSwk2jCNzq<;8 z1DhBITAZGE?3lgmE4{&k&!0=k8Z`_KJ0)bOi>%J^epCekvETmdpfPtOcmFCKUrQ-WGJhtMzl~?Bevs2NIftofam~rG&ayK` z$81I;kB2qKDU~hZ$wfz7GO#m?nwAwMMyI&}wb)& zV%!K=pu)s&(ix!zNdR6BD7XLlkg@e(tG;?_oIJC{@U|2EZYNG|tN+%=^Frj445{e9 zVAXs+1|1wx3Ozo?RT~a#+fY=-=g0ayI5Z3-Gt9)Hky3a@1(uFL~r`4 z)f1Ep7LQa?VD&8_T7{`wOcWSj!4}3J4zTejG<)r1)^-TEE(nGfo9?(M(^*s}dk2}r zaiD3&l#~Q?z&X?8p`!dhYhW}ejC?~v0}G?o+YS$k0nv=V;tF5PlW$gi<#2i6+|lvI z%r%phYPyO=yMAgShtZwPVQFMiu-(zZSoKvkwks1;W1w6p+EwhRyi~v&K(IRbfb!^8 z{I$zxrO@;&V8%X>fa8z1K@9spE+~&c)!%O?c_5%(21=Hd{kctO*bUUNE z$e-9X{i587}E+sI9E z`LOZgj=uu*a0KnN&(PHaP!%l(W2~mG(d)AW@9gFqD7Z2`g*%rohrvvWoSHb86OEtCnnR ztHI(DNx(EWCq+1zEYL%uj&&O_0DZ`yFAIRJknmOZ7dMNEIkcTGdn5a!xbmD);^Ala zMXf&)Sh{d@+}ikPxWI$a9aNl=PJ2LE6XEmub+CMMfAO7J>etT6LHlFy-JdvEL70cp~E34xH1-e1Yf>vz82nfqP{5lBJ;vj2}s-n;kRGIQq4 znVB-9ZC+$g5gLMTo%9IfncHzL>m_bk6I$4tvXJR`_8{}u-+myV0k8K8G zcyk1ULE-o(Y!NC56y#h|>Ea2{h{Z?->pT{)kfG9HCc-g1pV@X-+GC3bK+Cj4d6~&3 zhJ7Y%Ck9hjZnsNUoSwu^9T^EbV#dB*(;V~EXASQzG_$#LvKXdZ$$cP30A`=h+<3tV z>5o^81hnv_hVceMX+!&O+hw?NhUOLKO;9|ApT33KfBqLBt z@YB{2@Qf+D57Il(vVZiJ#};azy!Avdt|9vDkTKy*ZJW?V6uW+B3;Xk{Tln(LO>9`Y zUKyHhZNq?1KJYgI(k19`E5KHj`Zw5|-4*RF0^0~1`$gNz{pX6|LqVq zf7T#rKsF5SiN1&s@DVUkzXnKj-2ttN%_U82LvbTpv#p*l-B8EtTRgN7;Qf>J0fgjj z!f7=gZPK{3VeT|kp=0Xs&W=4z55DomHa7Qk(k)fnxDoMJe)r%{ykxIEKxS;HM-`w3 zqor(Tva^|1(MO;b%^A_k_+90;Pext*>CnQQXg(ktDlRC9tiZOH*?Eh@CnZMd0-5NK zb4EqB!8Fi;_Gv_;(2BnlEwvMy@g;Eoyf@%i8VpUXt*@(#s&LotQ?O~=nqzOZA!x^D zqfy(4ZH6c;O?=P{tk-I74bEk~cl6U+fN7jY9wZI$%z@!oYd*7EqhhK|de07oa)#tw zih`&bdPG?FE3Cz<1Zo04m!0a?+p@d!ewPdY;BUd|wra_Sn)HD=h+R&7QtgT?7QX1; zeQ2UI>$aZ;MH)S)3{2DQK&J)=cI15>ql`p|s#c#lDck(`O=Bcd^b;DZV(%0%3cLda z=smPg_4{Ww^RHJmDA==9V4F?OR}dnQEy8TJt|`!3-^HF~M_kUrq*wUq-)3tO`3>bL zSaBQK$z#&k%FQ(pe{-o2c%q3Cg^K};UT%Y^eow7i8Zg-E!&NsTZ24r1qgPHJpo0JN z+U<>}pF1rpG&|sc`a+b>p1pan^zF(T_T-g$2tSO$lO!ULJ6twBmckNC?<}@I5g8d> z?4HES<}9^40AjmH5x6B^2HCTw=87Rn9eUNlm+GP>Ric7t)nSVu0741xE|0>T9!0_m zksdO_|Bbdou&8S6*I`iRV%0;hbvJ+Pg@Or)kiTASJ6WUU-^XZURu&btbavf*YFxC@ zKOj3sPm%-zZpG$$NG>#fnCZ1al!dw~9?#(iVG7m1Zx870Km2!P!{v8fm@CCt$Qc6i z7dT~XM`atg>Le1Y(4t*zzZ_2KXd62`<(>BGr<=cCxv|Rn;Pn&asiV{P%ZiGnR8`-~ zzFuC*-u|YPZ`{?wa^v;E-;9XxVSlv+Fq8qn^=RCm;jw8w1=R6vV6N^?{**spL0u&8 z+_8b>!_qCMZ>aF!@aE^6e}l+s(HL)(!n|09pg~eJbUDZmi4&84ZIg@dt!afvIUgKc zOB`lp{#cVF7sPA*Q}QC+)wV#ef0DiuaFsw-um>8xU&^sB zT#JZ4%`LU9ZM5PCqN$mW1gxSBDR0n_9}{bnCYw2ekxXMlc#3Ll(UC3}ZXcCNv^xYv zu;MuyV~H8?K?2(fW}s0U#WY5bDmk~fSfHki1s36%(DQiw$fhnC04g5NfZqJz+g*2F zIeUN@?nC1e?nrFZfH-#L>^%0~w|g!alA-$=GqHmj1UK6!6w2cWr1`n&k*1gaGzI;f z#Qj)@(&!i-HBlg;oa|UH`^y?$Uel(WIoJ}6GHdH_V*~E}faz+5tVPW3mBJLIyM%h; zwDH+2Dc-6w98@t;E@xv36XD;V<~E``Vw2QAdgS|cjSQwsJjtph=L2?)B)9pTz2ow{ zKK}lfODj%$NvNz)Ey&5r8DkSjS_>Y>D{vF;4Kv3?O0WKCPjmW$r@;K@8_iHS zZc*({!#F^^b}886^k4?3>QRd$(GMU_#WS7a0zRS30uS`)XR90xlP&g#WoY^0ad;wV z-4~JYn-v?Y7woNZLIWHO6te6|{s`Q}v5gUpkg;Pl!QkFhSa2W<8f?O8%;eFTP*H&{ z8(l#GA1~a?;f#kY09>Gw7Vz3GP-qw(;rD*+lcISJbABsWm zq8RjJv#d|TtJ1d)H=l$+JYyU!w$wdMEfxry^k_=*o6X>Bfsahn`6G-5xcQY`Fv*19 z0q#P+WOCUuAj!}OX0jS2xEnOJ#p%}eIGk)}7?1St*#+#iEe+bT+N$R3>T6ntSq)P3 z3H?kgBU(p_C0MAiO(4{TJjge>Wq0$UBQ&nkgae%UW=7d-v*IH^>6d6IM$a6K_Razw zLL>vn&e%Q!JP`FuH3)fG2~mGF2En?3S84Kk+MKjCakM91f*WllCe|a}R(+NKu>^Cs z7ywlK#kD&c?_9a1o>Am2!nm4fbZ6|WNomsapX`dmTr(Q1d7Y<7*b?t2nhn1bE`hlK z03ZNKL_t*1S4RvAgWxp_(jMeU9{{D&!anFeT~ftve`W)ZG0K5iL#=+jPJ(F&--t=z zN6d`NU4D5FbVYmWa3KICH4q#kA)@lM+dz{bt%K>5@IlH*1Qh+z9ZLWFq#T~Sv@ipZ z;P*wThbfwqG{nWt!~go!=JfsRi=`FvjPWpu3YA6Kh2hx;o7z@%j}*Y@0B#^mA^R`@Wdq8pcz~j)ahE?yLyfL5X^mZ zAe&}fNFBNuP7vBFeCAT3&N1GbyMTiOFmD^^#BQ!)+Ea|->t z^9RRV@AUd7SGNRaHr6y1)KoS`Lb9d9Br6rf%gW@ONH-L!Xg}3~R%yUsUx|KG42{n1 z&|lr<_enLqG35%wPErHVQR~d2*0M-uazq)mdn3%o6=>f~&_xn@PYj3)B2p-{B7v@< z#K~!Lgwm8kL2;U)EZKzFs~N;-gME#S1w1xM@3tLA-wuOy)Q+UbGJm*rH8U%J2B$n0 z^&)q`G3XTJER3}1H^N?MGxs>FkCGXiXMVP$(w$^+LOOx{d|j-}6%)oZxG<66dW^f^ z{?o40D0XkKt+ly{d5?8ROGm9S{|5`|E(1^o#n4x;e{|_3KRkb?Y%zdDMN%h#szx`Q z&QpXnX)sm=TdZ13B_5dZ{p03v&b<`0_mXu@r1akJb0zLtNt zx|Y#IG%!VvflP)wND^DZ7j!^^IL%&$0is7@%McV_|FEL$)*YoyjP@$Ur1(qlXrvPN z=KsXB(SXl;+_M&+JkEj1Ri?yu4mWYJ-+Z{St#F8fuU^> zIwgFFH9Fx)d=Mjjxr4`9WDh*@rQ#CQezoS(A|ZxqZ!fPec=h`2bsI*W|6U}*Yf=cbsr_-r#Td zRJ43Bao&5A$;GtQti$p`SQiK@u*ty=_ssUaj#iX{& zCbpEB43X}Esd}uI<^E`=EKH=t-G?}UzQ^5db505Sh>H~JIUJFM`3c`kBvc+m!mi+Z@OFcXdsiw=+RX8HdHJdB6k zYriNcS0P5{`uvQ@jMwfvQ6ljzx+5#Ev9p=CE#@%>#XByS%pCaJFmn55_i|g+LQei% zj!eQJmJBg>#p5?m&|Y$8K8jVC&*x*WeObaD`1d9bUpW2~@=Z#lN!yGma5tb>18Q9k zZh8||F4YXCAwAi%>{ts}0K5rB!1M0BY_#^&2^p+k8fl!PZ-Og<7Q5IQARPdY*TKyE`HyY)&FncR_@y=25pezJx z3GMfj=%2EuqaAAan@U~mqos}ft2It``Vgx-IYPS@3UTkiZRgk9g7(TaYdEbeMFM{1 z;mIr$qt6|P-ghF@_)>sx6DD}s0A>%SeppD$WJv+XI*ioHg9vI7h_`Co5WmB%GONG< zwj9X#-p3u=-&)Bi?5C(J#J(EsSWCR4RhsJX1` zMuIV+Jztg*rSWIQ8XVM~pxW<{{}(Q9D}H}Dr+wb`)GtnowEN||4I25Rtax2aL6QLi z7qM^s4Ky168?0{K^~xSj6WlSCfOBbnHZ#cSQK`V{P)vFw!M|aX9_EW&DM2Mx!iUAS zz*=X^;nHrn!qmQ}=QCYGY=jl2NU?B&6$7n6E80j;&xq9?gFk(VJ77y~=YE5;uGQu~ z(yKkf!5nzHL0BXWCL2vS2u~PpI{LA7Mti++*v8r1?qlJ9dorT-fc})$V`N&|6DB29 zk`R_1w7tLmxrPSjz?A-G2Ue7; zG0DE`3wVF1TIsG`cmx>$Y8r^B=3xSRwWuIYBG<&rHrDYbID8qIY2X9keiFig8q9#( z!5xtO8gWVN~14F?2XGZbtRI3z$AV95cKA0u7 z@-2HDq(!Sx^f!ob8^J_xz@+tMFcA0wrZMGTm2i@h^eR!i6v1KJ?t0CeHg|ApQjCEY zWLl+o_y(Z;|9a@#l~%X$nijtdDUCvHH9W%@NQfXsNVXgjn-6_bV7X^`Yg5Nb1^G&t zAoPieQR(o=I~w!wC|n|kP$mKxbpdk+WlstI58%fK(ibvg!S*osk=PhGFUO>{jl21- zJ?mRrI?@8=O%okL<0WDre<0kC4aABk8N_IT!~%Be`!hcpXSYH~2y<-krm6KF`p12I4biBd^P5N>BV%w{O`tF%**_!cO! z?_nz(_P$(!3V6mdW26+F2!~At*oYsDm18z=5sRssO!|=EqaNFM&?0Ywl)V-r@p8%U z-`yI}Rk5`#tp|gL^2Q2LODn_(nQ38>1-=U5_OL#uRU(~}xROM&;vAO$r100BeOSsH z?+`AvFoBVqLXM=O$u$a+2Obl`p^T~AaG7K-<0@nRL+wFQ-cvA%CX7eaJ|B}vT-?<= zROaz?90SKOa2x~wzhIz83;-boWkpG7*~nQbU_pZY*Ujedd0$W4Yl8CU+t;`8;N; zR95Vf(>v4wQ{4Dx3rLRii1tI9rN$$Ilc?i z7BC-T#ZF2^(0@QIZjB3JYaDJj+)e78t`Ao9oibNXVLtx+aSR;Cz;O&5$H1?LfgUpe z1S(B7q^M)bX1cJ5k`z{ctrZr)*-wFnG*!b9*N*fyL>L!gr6nU)vO2H<;U*=8rK6?H z(-D@iGEsO19p2LoD^8I)7+@sHyjZ!1;XQslj)CJCIF5ni82JAK1Bb-`{QrTP?S6aSU|Ez#$z0L8MHv->2gP zWikdIw~Wlz=tJinKV&~nzr#m5Cm#Uxn?7_-9}+v$hwQ3!c@qdX&#_?<0KH^p)rw<;{Q@;Wcpj(jTESt6iSJE6D#1d_?+MN2Bu5buA)Vlx{X7?Zl&dInWwRw~`Fp)lh zbMmorSaZcew*XMsi8`(PU8F^)O@TWoa!U&DaKalLor@2Qz~DrNqLo4K4SMB=nPAWF zft}Z99zVMtSv2EA^*O8x9S#VnD@j7mH5=rI-CiYoM88Njd3cUJD_%Z-1{i@uX`*)p3+(d$Dr@BH=g%G@BTlB`dq%UD#czSMogA%(m4NndLOu)e`33Fc+1WRPzCkB#Yx64C;<;mT;yN5$9O-v} zzg&zl8;9qbESH@eBT-y|Z`RrQhbx>sLd$+Ty@-9oRxsa@P|iJ^x&hvFxP@Mu7_Eyx z=Y&|<4{w`qEoxF+p5WpWW7$k!9rG^g1NufeXTzoX2N?+_;dUB6L*UAc-#lUjT)!V< z!E^|ZfHxjv^!K3uVThcmw82aWt0bQi;B!x4>~rAcm|Rp6?7dClwwgR7T0V7Dv=qeL z`^q9 zJu3=1D8oI3iKS<}Uc`roA-5ME@ce>V2rxg~x&`5x&X1@b2v3W1Vi@3z6-SEGuHass z&C8zpw2{{|`?sHx$|mY8tnF|r(^X{;bRTt{gpk5-!Dc@FikaEcyi+rzq-fZ*QC-Qh zjgF|B_zj+<25yg^{IHyVvaE?Cj>>)0hOnoMYnivFg9pl;4*vjOFMjPpc~oIi2&eFJ z)9PVQy}p+J?X3+Q?w3p9D*d|AUiRanKIrfVs{jA$HQ?_e_^N;HvwQR8v=}gH?jXD6 z-&K6=Zcp9xete8R0v+NQwQvCJCxcn}=AtRlQc<2!TC&x}KUwJvX2r2VMft33Zht{#LlK9Y5{802k5{jCMhU6%u91)~t)C3ov*++V6B zST%P{&e6Z!WN&NkjkOi<5{uwuH482;)XzUX6XRQueZ07m-TaR&Jjx{hep*4)D+lx8 zaU|=0sJszoe93^!h>0)VStO+=n&A00fEX*g`P1*021aCRM`xM+yL;o|^-yL1n)ir? z;Rn0r)^jp-SI|kQs^CQo#6Mj) zJu73)OVi{#E*u~w#|cMw#BQRNo$JY1N}QfOenr0Y{EhiCgdX?*w3R($8WRys-sgG< z?`fw^%nghllA@Ls!ZSjlviq(YCvE#=o;>H&et90h^z|B}W=W)ujhYIR#~zl^hZs9{ zvH}hYu@Zjn+8K#*TAb>Dz+#lyQOp2B#5h*k|(d17BW4SMY5MS+#K&WelfD`Z0 zW1-9RuKJq#K3%6z`1J&=y8ET-!H7y{X@YF1H^~wue1eON`t}P1(jTk-ov8`t%m4Gl ziPE318iFXsA-n+~wVniSxSspUCwS@lv=K4vwcGp4?tnD^yB+R74v{T!gnZ;3s`0*e z4szxuX$ciUNDvHF2q~0*Qml#n?T!kP1!tMt-Gkp`Ae1AY(6IY{yU zo0m~MkfuA)S6UTGv_vJ4d)`ptmSO!9h^|D3q2t|GjFo%=p0KMybLFuz zaUBX#fH_>3Lp|2#_fYQ58jXC~i#O!R#2^yxsJn$zWfMG3!M(IaFOSw}l>Uf{8F8e> zoN$@lI8tB{7Ht8_Lcr3PLu150Dp-q9~3 zl0tig#$od2#@OiyA&%nYoJ2$Fo@U>ugu-8+DI&lzQC*&!YEg1htzymySDRqIYF3ui z;^t>6l7FI(MJ7><3wr0*On@&RpG)w$0H63?!eTEfHgr zD{vYd-{q3uR+M+JdHok)9PGiZEl#hreGlnaAPEW-)4f_S01%+i^-lChgIO3jdMNa& znh#}#Kl-N}_Pd84w$>nvGHKFrYnWLhCA8+lKY1S~AmC_BL!x<*eI&b*YeV%*qaYclYV?*mNaZY!c3Q6+VQ!D{UgDGD1JR?=x)ICKk*1eVNXE{ z6ZP;V85DU?v{RVgi1wOW6&7KXlMyvkQG_~? z6ysr&LF+{30jo*dgx?n(E#?(vjmQ4>lTTieC1)iW)UgJ*3o~5~x56HLzlrxt)cJsS z#1)qlgOb)1ii+9i_~=1~LJ6 zX#AKl0dZ-tLf&2zI2RsSb7GRCI!e&!jiZ(TE5fI1UIvIe(-O=tCqx_Ggq!*rh;HYF zq{IiCa}Nch-HAx6wC^9DZo_n(9HXO{IK0ivhLT5GtL%xKBKW04Ww-C%0fE6Fv&*QL zzPs?w|MHbvYM}(@$G$^o-lli=K_POYK}o$#V5xuN0>0=`x(&pHFYR|O8WW`V#hO-D zYYR%*33`m{JQ-Du&_=bdg4*Bh%?V(*7@7a~&UuBp7w;M`kqD)o`jK&XBB3*?^M(>T z`+0i{_LrgK0Ql8vUBsnWJ@+!MeF2|&C57v}F;4ehCo+v9OU6gR*1|JE}TXP=kHf!W={=q~4(R2(^VP z8iPE-q(Pud8oi;1Meiay95x_P@&tJ*+)Wl9Ym5%s!-!~^tFw|L zZu`eQ)2++iynx+*{iIk7gs**XV&_6qW;v3K0LqWXHp^F+PEVAkkBIKjZ`HnwP~7ag z7iziB%l+f?%oIry@%Ok#(#ye!wV^I|5Q0J88Tcd}IcG7u{xLBj*)DLokM2{^!RLXN+)7`2QRKkX?r_N*$lk&<%|N{H|#DkWof zvHaRhkwGv0?ZjaT(v%VKv`%oUT}C~}4@~~-;#1P3vL^p1j?mU}kjHh9ptV==D4qNv z(yF`U`{!p!TRxa0@BHL^`LUbEAhNaeYITX`yt!kUb!yMIa@WHejj!KLUggzVgy$;y z4V@8=D5}KGr7C(&q$$6B?C7$}2VEWMef)x|TE~wkU-{{y&@ z9z2@vHf?ae8dynV7BNIU10{_N(tBcy@3F#(G zcH@gRd~muU5M`pc2NdpC@rPp+91FDryih!mVxYVz2Cp!2R5$zC9xyJ$(~M-^hnS6s zskASBw|Z;sLv>9qmKck@PohZ>U<~$xAP&}pDl)l-$H{3z?0Kw&IKDhK(vZLAgZa7$ z=mU`g?Z|>eR#9V@Uj20IBi0CWaqD1|M0$S)7 zV#{DfZ!CchR2J;1Hh}?{bmka%S*HO=KqRpUvj+RV5{DEZI?jR!mwK%kBKnTBa-i%w zUmF3-6YZrlvc(><5)4_CilItkPrO&E6eJrELrsGEA%s#vF6Vj#20Q0-RDJ`F;b^im z?z?;lwPJgs(NHL7hpt>WJxzM%lX6S7%{L(>TEB6ak=5bdJ~f$aFZ>WE7K7&Y1y_%e zM-2)ocB8+}pV6O{S2?9m7nRkM?wst_ATo3bu z##n8z#iaP{ve)bIyWFkL=GNAx`qs9pDu=tg((WlOw|h#;9NwLK9NywRPG50ZtFO4+ z<=eTp4Ij6!q|)Q_dlk>jVG;Jhsm4k)YYF<`E=193!78Xv1_#vVN-!_ayn5dx>6~d< zYV(DekkAov*4aHTZslj*v4WSDJN%~=T6~v`k7~SlTvX}ge&#(N{Z!|>?1^n0qBAjg zgZk)S49L+IExYRU1i7p!FbigpL#4ybe4l94$sa{o^ri4|@D6?t#3x*l!zu}c`cO=yF5$M{rm6W5IzkB%8QJ~s)bad8 zoiaMh*os>enX(LW^A^NbC;R4OC0!3XjD$uyXh*F8wefpP9f%w$`(w@8HcaoW0j_u` z6fXgd=hlGP-uuFP8w9}#n!r1=rsOe)J80NZ>l=s(BHHbVAf?#@_UB)r@&Q7 z(TZqx!n~o(+?R@&ZZBWCtA==30tLt;il+~LCPrx??o|+MOp1g%0}}<&>I`oezng#; zFIM-cvYK(YXO`8pvC0OoT##g-Dc^y+EnqS{4OA#df#{r=h*?pM56Gp6s=ES=_(W8Q*wEO zQG@cZt&Bgl$>=Dt8_pXjmDhO&R<`&B?Za~k?bXvG-AXXh_*Y4#o7SBoQJzE{)UQB? zbgsj<3Cy;hf}eFOQ#|yGNeVDsfmQzV_g+0to;f+2xnZFE@Jp)=UoR`qnKd-xEvrF- z(*Z5r47GbW@9vqM505fkB`&UaV3*u@Y2%$sc9z?nm=JRwqR z2b@)asSI^3&yLqOMVd6$AGSNMz5C@-%M(}TiaJnZpd*S(&6^g-UizlNu(8@ZwJUzb87v*bZAe!5;u=M(o$!bY20wV0xzf z_?z3Z-}rjZe~Y(D%VPBWx~Y=1ZPBk_I%qOz-hi^o+}YFe*{DGY(&9B$*Mq2B(bK}0DE(>osG*effjiS=&?pC zb9=zPkNNd`gZDoD#_CtEyI{D6R{m7)ob*U`@0DYuzx;dk(9}pxCK#>=FrBob?h$Se zi16ND-1Oh2rObm6jwGHHoeYhVmmbX~3`=Ias+xY25v|*(i!j$sfeI6f>ytJDj?=I; z^wJ+M%$BoYc_jJ{=tJ%AjBP1%vxnZR<0tep^H{645%)JCdgfx7DX(wxw>BKitPTv= zAEuAbk{`Kwk}#Vllexd%FlYKAdMSr-v4XrCl@-GUD*;TCKIh&Vo%lYs=lK zllxoVz${*knH2VhC=#*T0T-goV)Dlyi7z3Ngl;WG!$Vv?fQSiLz)H^%KpIY)1N#!i zdB<>vH#CS<4<|SpxvqMHt=F9i1azt_OYb~=%UEgV2^pd;0%0LUQU_SJsexVmz|TAh zE3mVMM)p0l1B}Qzpm__BPyy<5#F-f@NYU^3d`06+(}qV&r$aoaHV2vlCuVGg zTnQ<_i(fTN8krdwDD$Ywq9QwOp6xZ>cyM#vYSyU( zjVOU=pSCCndGt|#hi-|op=iP$xptUz#jIR*?~9uzF51wr{$~yQH^#twu`+4wYY}A_ z{?13#B^%e~E_>}^S@The}8xL2Z~N};+!JuZoqWV@WThlQvxQ>4UArY1RQvYjJsLko$^DeQqaE+!q6KXRvzo z8+ehSQ}g-wff1USW3lhb(XT{JIQz$!O&nV2f$TV)6SP^0UQp`i!4~VTeFFnJ|GVf* z_doF5@|>sdm`dXx5>^!#3}f$pU94SN+Iqzqg_bqB!I);0bu85R!#217A6s`dvXKyl ziops%Q=P9qcc^sb{om)pgn6(|tKX3@zKt}EyEO<>tq+y3T6}+GzX;vjX(*G%E-I0* z1)_k1FLv{bl}f)veK0p(?*wrcqmM5IzE|rst(9N=d~o||EQm%=9-R@Ic?9K&%1j%Z zF8#E&atN0+lfZv1nxE|~1OC0#uMY)hH}37N!?vhMl$F}x;%9uMhLt*fv^i>#6xl$* z$GVYU$47=BOKJR&gpSv6&e^)1cAj9xnhlc;iY$kgZLL3OBfIinr4Jc(n#WHapThcO z!YQIasfq|fFC8pjl6h(>R3S zTezl%lze%NMH2^LGP$CO#P*F)_@t-0kwhg08ag~ozv+Xq57RP+K$?epkoJ2R$da+I z6*orMriamr2^+bO2j}kf2lK(bSa={%=k#i~HTs+z8r&`Gg3gw80heu!(`H-kaM)Km zTkJnO?e^u8>{u?#j%5f#zmz`yfco(STb6YE&~S0;{uZg{ zxe*ihvvcnXq#L0hk@Ls7*{C6Et7a*PJ^(YyyI-&7c?r5eQj`{}U#S?frWMeV-qg_G zZiF|pKABj$021mz%h}EN-t`E zf8gzE4rfupF}Y^1knAz(XDE!VXq9*wh3E#%9r3*%4!|fxr^J)_88w`Gi`tPA4v>IK zW1zU1$)cknb_hQqZXfPf4Yqfn^-Z~<1S&U_qAVIR0mYI^GGnQwhYffLlJFB<9*1YA zSUKr#(VL=5p&ZukwDCBL7OOUHL&H^LGO;zRIQRml%aVHW02*q% zYgtB&)(;q=b^;gRSSHi;9whQ{(t*0vMkDeFt!D{M>ct*p+F1f1%u1{#y+C+7?coIG zJQ5WBuzZmUVTHcg=x!;0eL5l(zWy<3?BOj9{PH(`sEhjD zsn7>%@0^@PgCm_WI+Cr}-a27Gis1_*i!PtSY=omjPDChMkT~*>j*X&yQ~V4OH-4b6 zO8{d)oWB_OoA{!&)$I8Xx3Pz>E0RtauCA=aW1%{U!2;B9!mxPu5&5_yq^Uo?y(0i&67#bLKT~XYhe>BulFgx84*eT^eZq3tfk3cD?92B zCeA%zK}YZ+>QDp;*h7zBkt4^!n-eM_nu%O#-}8Dc&ri?=ld$E4HYt%g+XO$*m8C|u z-zt*Y3vIV(`)28js}_7aW9jSXlNyLfgK}fpgV&Cg7Cg7|;?yY3io`gxV@g?D18yFY z=8j;MMb_B1c=nCYw~c?~=E*WSw4uqErdTl9?3#0j$j`jBe#nR{o@ep1Vhqw`DtOQd zxGPwJ;}nSgU%2<89GM*E09|SqBI*O7e7&ZHeYVoZu!YG{d@XLT#{=-8=r1W%Tuub` z*hjRT3PavxvJst|5hePe*mk04khQ(l2im3|(7u+Xc(1`1QhK0ky-L)6QVX_+;;bNa z06_Fk9mN7W5r~3;Oip_oI=!`LD?Vf~XmD;cWhwxqd}#}S=&_`-O@i(dZOPccHZ?#m z%C)E$?IH>|%r9vEKYB70p8JPZ|5SHDLpZ+sLnT|jrJ1eV*22aPBrA{5Vhoj;GdW3m z<-b+YwzlB#7^`+&ZY!%n8y?9quVW2`nFbW$#kGAfs}fvnjZ#B;AkB4vZ}gy_(<9wY zcsoP{c!OGxUZxM32ZA~1NnUtMO`%~V{F6}t3T82bs>3DF1@stao1bG5W#$o>ks2|AwK!^`q4}%Q-{g_yCMDJqMy2T0-+2^ zMU{FEwcX7P?6QYe@X^_!$zQA-r5`aueeDhURYa!?R5e^0xC94XZgY)}e z{HhjXHS!H*igHCM7fy+h>KwrYnCgu5b0sNbXpcM^#>Yn!4~9gv63Uzg9b2nUI=R5& z;~sbGId?AP=iR-C@7n7S0|OPT4tfNS3J{!yuz9Csuw~Cql+QmYHKox^GPw z6s4Ip9^y(-FOi`*t!ehLCqAy_W3o-~i6UV?mu&%=uJtRy^3r9@4Sc8%A0q!FeG4=} zPK*9~!IVU4>M$rVsaT=z#9sfQnUy#Al+ih63N(dnCbj`fukEdE?v?{dF6dgchF`y< ztl9hQdmBYoR6)w?>N$mM?2shwnhNg&@D`GvJv`cqvOD+fBVFD7^2dz&DO`VhKKgE_ zpiR*np}un2*@IcDS26Fb^-g6vIjuXAvi&me^aD74dqjSO?!uFj+v%Skq5f0X;$wHc zQo%=MnG{S2%|O>S;CngrjJDRbxDJTxPT3dI?}BXd7lOA@2dV~10KO{-i;l3=hPs)l_+S;uuzhwMY0!LgV$Cl1Vsrr}B?%9qj} zC;)F|kxc|DEP>nb`LKzNFw&JAG7Ywwb zPal-=qW z{d=pOvzC^6UXG11y)boT(!H0QnK$Rk+4&Q0n$vH{HD~9Intw+2%#(}a|Bw`;e* zlR%_d0h7f#r~9_L@i6sLn>a-9lzX$oLplHwBn*xTdFC}|46%H$WoJY6q^rK+cl~o6 zw_$dtvIRAS+b#4yxn*8(X@BY4$3{tmb0VhN0@Bu>wd_xY34QM}6Ex!p29&#RdUTOO z^g{3u?x_tZ-F@i@DK6S*T(#SCyHV0)=S~z`B%NtcJd66A1G*mnmn-^*@PW%=>PMb` zdZUuZL18IB5&OB&<3u5ABq_MVQ0MCP_K^Uf558bB`f7T-A?}YCW&v_k1BjsJ*;D6b zPkvg*$LFfd3$ATNUDvq-fr^H$2i}VYZh3zW=9^`|M2 zsB4m!>~i0wF$azXH^@E&v3c&W_r6}iv2EusOfj_Lf!*luKSRQ|q0Mfu>!y@wL{4gC z(2T$zq5x_`({ zD0dKahy^rsxBv=qX_V*;;rak4q?rmjsaF%^Z3eHdr_7a3^?f2T#TRO6Rz6sd7Q%vAs1VY2FqY<2_z=%Of@>92t({F$OY_|EG+4B1jPnI6O zW(2!)-XM0}Z~L*E&+W$+TsDxsdUuhu=EW1`wJ%I$kNmEmb=rv7i%|LRVZ&OE#yxxL z5n6$wAIt(`u6^sz)8+P+H0lth;QD3{n{)RfB|SsS!u>^mZbYyo zN>C&tMX{2&2;FCA7Fuq?-tkKx{!r#Dn*U$^ug`Xi$c!psgke&T1Y^H+3w!^*;nLIB z^w*kA+I#jmq>?BLJNewfQlIV_V+8ygL{cTUKCwhlKH;9qrz44ipZmiExylw8v!mWO z+oz~*J3Chxza!zu<>gz?&5_BxM;!r?U1%)&W^FTDy4A@i=9{oRD^(%$^@=2IaC)@0 zVBUOPwIAW~NGH@`9;o5$XK(B;>&ZX|1>zcJ3eIkQse)(3=%Dzgw*xgLcy4ufn3qM6 z_Wd@Qy#a=L$)$h%hSOfCiV|`iZD#+zZ;D)D3!JvDGB78`6cZ1@Ku=s#_bE!K4L}Re zuisHGuiH_FywzSvIG}XH`9q~TyFb3F#Xmt42&VK4Q*Y<19N0jnjc8h4-|s;mwwN;w6M=_Z{FA2m2xs4=TGP}`Bp+ELcRql_AC zwMbqpHQWJNLz;Wx$LNv6N`OmD4lw5uG%xA{v{Bt?>xT-!H5r4CR^t~^hj52KWO=}s z7CK&$VRyPHN1a4)+*#2IZ45bp>BEJK%?R)6YHc|DZJ9#?a)_INF&7p+XWuywcK@gq z(F@g|>JAA7d-9!Pr4Swwp)^~M^_}m_6?Fn1^aMRiF_Ls_$LOimjWgD}MasRil*jz#kO4K|EjRI_d;I2hd5%ydRC(~%ro z;TCD!3kg6^e4qS+0f>n(sGF1_w1)aC`{2>((x*?JDxG_B9vqT{#nc3aXdM9vehH{l zFgZAVJv;k^B=+3R1Ep2}D3UIjo}7j@{AiV)y;~H+BB%BtBY?)wgt^Z94_rG&DjGye zXew^0Aq0}J$2IT1pST903*r6C1Gx9#k!6TRxJdB^w(JbJn!CF{P7Nn3?4?b6+E`VS z4_T=liHfB2(~A&_&KZobw*?1DT5VEnT=%vC%m!^|R#|#{*O&5CaFb}~9IWX_@#e4X-EB3Z$5zcw+;6!%GnfYvMt^ZoE zT7%*ftx=sNB+#LG3?WJ_SIo%RM_0&z{+x*VhgF?2Jl)76j9O^Dlj59$tq0GZQr2=v zWv+H$j_?W4*dLws9ulY zWQIy7!2MPXY%2py-nljCbaXd*r^Tq7GQ1#3h!Q*2!G|cP6?HBt$}D@)tS&@1b?X&J zpRJfNxhXzGPi-#~NK@%3R8`3Tq5UNX$o)(AQx=9NIVZ&`Cd!U)?kIQiXcKxKOxf{F z3kR>@-qj-!b@!n-#FOxcwqU}LL^zHjVKk}+VCX=2`0S@jR^Q^~gHnwyh&}ekn&sv1 z{7@zO06j+iixL({Z1T`(R$A{HfmgFMW)?N&FeOYP!|s2@WA(4X6M}_cqIPR`_&D@M z6u=YU;I3d5r~=#ly!Bvq+v$N`MqUCvZ~{adepm}(W(d%}bobLQ7=Q$t+(qu{s)bJJ z6HVI!;+(!iiB73w<6k|cchviWSUWr#6RBsn&&iNJzkiTqHEYk_>6SiA8QbFkI^mM{ zJAyc5*slI(^2k*E_2&&0hzWNbf`|U@`1@*JTy6_a9bkcnSgaZ`7=RgBtT6v(S6lZd z|8T)z&bK4LNZmK z)5aDL`RE3phuGI#b|Lapt50?}x#gCUpkG-sGSm3rtik3R5g&8Sya!h+7u>g!@2-YL zCH^Q0Tu_FgWJS=N`{rdy@82^}ijCA?Q0bGl{S?KfoSxr%4RXM)oRGsd!dc|sZ+LXE z;)X3aQ3us2oc{E?;fQpmwJzJ^xlt!+GCMlO0IWq=I$rt2wSyqRQ)!E+oZhFu$KJ0% z2|PGB-RJ_U_h9R0tv{&Q<_Ne20~api*E#}z1I!k`IdxR5=KQH-Yb|Pz_LSKAU2W{y zFY6fW&=p7p8gOY7*6^zt_m*~-c_IA9<*_QOPPyVQFRfwl5~%jU5RU(N`EaQ)H^#8K z!uJ?tjXA$&bTooh@dh9H;M-zW-%MM}zy%NzrtMoV9wAlQ0+}|KQlvHLli2v~(;x6W zj(GaVuNeeCSRII)$PAx{-`PvX#(~0ABT4#7K{KlrKikscZt0PAh(8d_8doTrjTK|B|XyHIX^aLO;YkoU2Eb2@v3g?h68@mca`Hup)Z< zj(&1Lkxp1%;=LVCG!pw@;<-hy(++y!PbX2^i*mwGUa05gZeP#qpw zrzpY2m}oYVxmb6^{-VkqzL3A-_9-uYwF(Ne;Y5XpevR#Kmg=1TR1}}#56V%P2#|0unt<{Jn1q)R`BwJTLxu9Jak24@PWJ7}8u`8Wi5KOE5<6VV}Nbw7j<^FtxnNe+osv3yG`Y=tq9<+^MOo zXh5{+$ST?3eN=w^u2%N$q6Ri8&%_}Lt%GjuM$rB`NY$#0YxmcjKODIG;vEc5&w;7R zeDq3HcY#O(|IFSNVAnra$_J(BgK053Y~V{fup{_0RJyh*Rc$?DUPw|kBY}MkM&s>y zcYlX?;3P4oQs9vbBfx75rb>QA&RnwF|3`#FNSiahdlIO=sDI}?uqXE;6oYGC{BW~6 zfOL4^LC)@d9>}iKW(qv?qHuRZ(%DNV6~s(-DDqJ$_>ngPYY2>_zO;jb~Uj`i#7l~A0aY_ z{I$&k57q52_u>TQ!XN|=WoX1e2T=PhL4f5WrVi{!(73H$5LdhXm6w@p5f7t`_Lpd^ zEU$A*FfsH3SFN(7ad>*ZN8O&^;hvyUcMQvql_m~L6#ZS)5U>%bUoEd@mGx~57F+PG zB2}XDTL&cS7h@5&_oKx%qDXcAQ4w>}Nb-~{OS>9;6X2F64L$*mMu4Dr=s1NM2AFI= zBME?4GU;SEyW>8H>Vr;O=w|nkg*DT@HtYBr1Vvy9B~lH6^}3|=#D#um1|Tv@I4Tci z-+@TN1*%j>9S)^o53;JEjctbi{8ihU*cK?**`biuF{#8G&W{?0v#cZ|yJ2Rc+~5jc zD=XR&aZ%>O4%-Ss9*C9VqtDzuS>5;V05hShw93J5d}4(#_k;JZCX5wZ6sG(HIM%x) zTXz+KI##Lu99;U>o6FjSlMz97RM}7)jU8Z;nq5jH_8imEVPmoA?vewArl^G!q-eSn zR8J)#&jv^U$dMGJ2|mE>#?rtSAOQn23l0KLap|#;wF$8L>;mUlM+vRk2SEP&gj#vUMUV!21l9z59ER&Rla81>v zK6BU0Wjq+*{!v*7J_9$!xUmYB-s`*pXH8G_XPUiy001BWNkl% zfmwNt5|DN=hoh&?#RfqqDwvrXDJCR=^hTE{H!mGS5*`!PzzIl+H9*IRBneQKY=b<( z9+bI@d0HS12vxSrY2us0T9=be~1KN$ttpe!n*{?Hr(?O-_e8AnE}un zC_-MS2JP)1`b|n0%Qn=pd;YnGpK#?@O8U%?_=t9(;0Ml48YCoNQQl5Mk ze4~q(L9_HnC6R6G`~{17Vub81NHsViS1Q5vW!Q*WBg@Vztf2R^x9(o4`#rT1zm!d2 z0;oJuSrkp>7iJil&8--~v8O-}AT}5obx379)Wrl*jxHe-@I~#RYFYKoZ5(=;Xe$ox z3U;J!uRno`2_@>NYu0f82WwlL4b9GSw}-DTNHqO@_AvAB63y(#JD%SjJp11De0zB~ zniOCSy-f##_pEU-?Cslg;geCG``t$8OGD(|ZO_nzd~y!^7ETR6y86$HG5LiSM<57l zC!(!Kt{W-ABV7Edz5c8AI{ZVR=kU~hmlnv;5&Qb73MOYSd{xbBn|(n9TcYLeUaYm& zVDR1IaoNe;@BUn82rozTfc6`JPWbwRm-dqfWy2Z>^$ZW6??Gy@aHE}1>2HSA7Iw)@ zS_dZdXE-|91EW*yxq>_EVWM};Rm>i34$k@Fr!wWOuXZ8_fmv~wT9nFen_I|=>jQVx zGG1~L?|coDKq9;_V({dQ6SG)aq6Lhg?<}sBvz5dM z3-#;$GU@OG_mZ*de)Rs!3S_LnL;0x>P`1x~QN^2`{@}hK1-Bc#|E40wg*0fE$I!sOXMBgrBrSWy?eLA|lM5y22qEvp{V3^>_?K0_Oe?7QuZ zE&)>?xFIJsLOykTx}ailNdUNJ=ivK zgK_iqL{TpUk%3G=Me2}0nMG2<9SB3E0E8Yr8cRBNG=V=+10WEcO=M2LzgoJNjlA$f zWhRws#6A8TF)OHS$o-psNM6&$84QDHfrOn;nuBj2Bqqq?<(3R-mrpy zwhW%jIwW-ffT`l#G9LV zX{94@VxAdDkt)F5V!xHI#7=sb-oHA4e9%*jZ2^cP%eR!bse~8mq*Q)>in`!$Xbq&p zJ#xG@=rebr*?X?Z=k~8jJ#~*#SjMFM2OrT-JQIW%P%^UY485=joqlL6TNk01 z?z;KOWgJ@Rf+*C+;_UW|21{cHC+JoIw{A~hKtfT>At%?vg`*qqdEgV^@uyx}+g{f& zZIhnIo%4swdz%A8yk0(7t7Gxl5ZTL!P5-=ar+iSF?+_FUdWr+9sE zs_6xU+WhC>RKv30KUd6mRnY_~@Iv@#KTnO-OOV(l$TH7EK!Moo?Cy(bkY57Idl~^c zE=(q(P+GIMN=HfcXSW02+AQJJRa-}tV^ea77zl;R4|Aw7@3 z@Zd%`9GGch&t9D-x44xHSM2s*g`gGj@YJRSzHzr_i5QZUMph5dZ+PUD4XnJH^s$hT zlOSN!bKYs$6zNOjbSpz2ziy~n3a;-f3=`S&J9%2P)}I-xv*UUR_PJI=^JPaP0x9)o z0#$+O{WrXpy`P?7N+yLg0z6CyE{Hd-e7ac4jnf746ZG)@MS~Yx5%5bJn8)60Z-vy> z#PH4Nr~K2X;or`^`+M$&Z`g48gv@{6GhT|Y=;N2{3Oo^M@Mp{{5^kaQp||(d?=lC1 z6FlcXE9#uee}3AdKHrWfxNn`7%b+|ZBaqhFFl5S#Nsc<;el6-V0ix>PJaRQ0#83?c zouJduA1ZzKzjyJpD6KyObb{?NNc;F2l)JOm+3GkPIx(Acr;33)GPs* z+PDNDxzMd+Td}n~B;Dx66o=J6--=al86=%zJBRA-_3>vvT~fzM;!CKaPdLpvF@bcA za?y4<7{p?aq)z}a8CevvTO>3I{Sh?v(BXnV9Ju=qZQ;s6UtQ0w0L+NfBj}v+SM$b} zkh%o`dr&YG2!H_=pdV8mBv2H?}xTWaN3KHV&^NI7BUz;1tfIZut!`A1}$TH)Me z7jV899qdCG9lQ=P>>E6&yz3809|eN`Pci0yu1Nk*!3@7YG{f+K)gagZw3)VSRiLSH z1!}1CqNU&^R*$@rLF$npx_z==@y5Zwz%f2Mq+h&l-b}cCraarL4b@**LR|6SVsf(@ zph*LjDF(~@Gxp;*%QfyMQldI|&ON&WmVaAG6~)U4y%(lF97&x5G)XLB3=hhdE<$&v zKsy)8Z8YAfnNX&5R^JQ)Lckc@fCx$P$`)If`*V0#=m)@~VJpPs(1hUY3zIa@oI2Qa zMO#~7%j^YP_?Ii21ki$*)FMTBV+UB+ZL<@ky)D5z>+F2oAcOUAq%$J#MXK%kJ6O5> ze8UsVQIv`(wM>MI1lRM_jU%M1X6H$RvLi$A5Ur@`ogZrv#jRDDkZYzkgYu8GR#5_* z{LDf68(sQr2xW7`4rr@e;oSSwSMDAuA{B~)sE%mE+g>Q)ZSX%oE)V|a5nKh=R>51x zs(?(KW-uFgSgr2?iz$6*lQKJ`@cyEo?L?zA7 z{#BF$vF70~AbO#I4qyvfBS^Ivy>7+oudFFJ65C*d^nOl04E7rffM-$=eQVxnFdE5; z1R1F~ruV7;f3dutt=;M5<8sZUEL(-k>(Ey=aYeX=J}f$c)FN+SE-U~9tkgl&Psv`J z5Sc>3;@K_l!#6d9zk=|LI9&o1L6`axb>o;!sa^`iP@%$ODDI0dw2PWm2iPzYR$}PcjpUT|- zg+~eg==IxIwMvdn4NWb@9%t)rm%~}wW@{~RD)y}|kBkA2+ley^QLzAxIxHcn!R{ww zrWwxy8wNuJ6u-LzJBVgD@;v7scb|m5t}+z#9#n2S@3x=y>_NmEn7V)m=m{cD^2kJx` zq}WS`y)kb?XhmO7G)R#be}4=2eXzn|<8`g2kuv-7w87@9GGn!G{{Dqh{@Qo6MWeO{ z4K(-{gTlP2Q7k7>r(0j?y9;hD^3ulkD1c9Uy{LRrSc}jGFJHO2KKSvXGOCqYQ0Oo) z3!!ZRP<)!8dmE(OE`>)0CTVXDhheH5yHDPu0pp2XGOY9pNv)dJ_1T z$Nu^IVRBA#nDbW)eeIiS_T%~%K6QYZOmndB&q!@^IZQQ6irw~ZM?>sR6-eTvO=9)2 z#^5<0FN8k8*Sqi-B{&28`}bz7F~2_DZrIb?8>}zZb9fJl}?C|9Ec2e z-)p;+5g7&!rn?EX-iG4VN^-F5aOnhXYxemSYfc)ua7IF@gire0Sx#YdwSKJl+CYys zD9*Svjy~Np&&o(JgjO{um}*QPbj~_^5aN1hlVdS}i+*2g_Xd2_CmPZdZBiV}yeTgv z>TC3)qW=GJ_Z@&$6x-jkdrNM5BaH+I2{j?K&_Sh$3JM~MilTx(yU*UAyGhV}zVrRg?7bmCNE3bU{|#h!@0OV}XWE%lTPY$XwvHS-8QJW1 zI_>RsjKs@--(ji0ug>q1vq*=_1DGg_!`FX3+mqM8Qu@L7Dg`IP?%yRjOXXVAv3fJD zfPT%ln^Z9XeNJ;3rMO5RHhxF|*g%d{-0IJmZ_xCfi<(7VT^+1Ww||s}!$SQ;Z8B8{ zfH*o>ps^moSQJWtJ=GV1NGlX`pxR^rgm6Vww8N;75;h@jtfX#e0V+M=E*wPwP(}-e zu@A?^Yo_}sjxX!0>hs6M>Z%ru3aCO53Q%8s7Y4ybw=C~6a&yt=X_mTA)0pY2?cBQd zAh**()AomZq?BfJ^8N#((dh_ebT|T<1`>E!tgzB9K{LO{yKzhuuPmH3n2jEaZVD`W zu|oM))R@_m@1{fR-v?$OtRB5OTLH^haVp(jG>{)T#Sw})gp)2(0DKULo=fEmc&M)U zNBS9fLMA=FFwoL<5vMt(ZzNo})0cDRiHp((SMrx;NWe{o3p0VY$_E-0G*69k9=DYHAy4VP+-?y)U4Hci6= zqe(UkxI|ss=iSvcl|9tV4(c>~`Ms~~f!P|(U&w~=MForc3Qnu&8+42Q9(uok2Vt@s z8tr3*_@fAeYBw~>^2ls%BPd?H@?T4UzaMP*f4c3W!P4pDB31m+5!K2lG_uD)xR3`r zlKWF1L{+zu(qcFL&-b`q#MPP=!gd82qqQBrf>LY~k6?E5=3<+%N|k;0lcKR>082Wq0ezWSK*Hm=qsH`v!sli7JXeXuOk$J2^lv+ew)W zcxc-Ni}yM|kTV0}hMC4UCF&P64B=@MO2(?2S~6#}Xf=-Bh)hJLJvg9UHGX={@>?%S zLBJ?gp;N#l@&IN1aSkGV>RpfyLG~{dx|y8out_zvp=e(WzJZc4d*`=3^%U_@?H{O@ zI>m5Cu{aL5IQv7naj;I~^SAf}KwZMgcSAJHxCy%|hSf8P03f!(510TlQsH(udP-n{ zC=LS`xUJe=0)u=2Pyzu&Tp_nc^2h|*-t7G1NRFQONO5a;P(aSqL53G6CHk&RjMRUL z)$kWA*grwMuny?mCs#Dpl8hO6?@InO1K{bWjtCK$Xlq>HBEP~0lNNXj^w&Zdt#;<_ z>}-MPDWH0$K6=ws%&SN^P`;G#jNQF*JMZJKaU$k7BIQ6_A*pUwS)HYMV;7SFz7IrQ zUxhX|sr5I)M6L<<&g;TUUSe#xUQjkvzIRfi25MO}wQu?waIT?-6&;s8jFp4fSck39$EDZ~OG+RPO2X!0QK8<3f<_|Hd&l=50wY~Ve@ zq*^j(Q-=Go=uj;ysIf25>ZHVous{lSL9g{VZ3ONI2D9g25>xZU2brRFVuT_mwOp#R znl1g_xUYd>K(ncdaQDlkD%{F|u6zc!Yb$92pt`7U|MN$*Go1a%e@;v3W4Ijz06{

PsKos5G0@ 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⁣6P%Zi=nv^v5(%ltF}yOXmKlJy`v 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 z48≷lnf3ql(idEg7&77{URCyz&ll(rrsM6-o@pk8}s2 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%0Db`` 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 literal 0 HcmV?d00001 diff --git a/packages/text-bitmap/test/resources/desyrel.xml b/packages/text-bitmap/test/resources/desyrel.xml new file mode 100755 index 00000000000..54fcdbba5c9 --- /dev/null +++ b/packages/text-bitmap/test/resources/desyrel.xml @@ -0,0 +1,1922 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/text/package.json b/packages/text/package.json index cb435885e1e..10606fa4b73 100644 --- a/packages/text/package.json +++ b/packages/text/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/text", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/text.js", - "module": "dist/esm/text.js", - "bundle": "dist/browser/text.js", + "module": "dist/esm/text.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/text.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/text.js" + } + } + }, "description": "Text via the Canvas API", "author": "Mat Groves", "contributors": [ @@ -20,15 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/settings": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/utils": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core", + "@pixi/sprite" + ] } diff --git a/packages/text/src/Text.ts b/packages/text/src/Text.ts index dcc95daa951..4d69a5e65f3 100644 --- a/packages/text/src/Text.ts +++ b/packages/text/src/Text.ts @@ -1,9 +1,6 @@ /* eslint max-depth: [2, 8] */ import { Sprite } from '@pixi/sprite'; -import { Texture } from '@pixi/core'; -import { settings } from '@pixi/settings'; -import { Rectangle } from '@pixi/math'; -import { sign, trimCanvas, hex2rgb, string2hex } from '@pixi/utils'; +import { Texture, settings, Rectangle, utils } from '@pixi/core'; import { TEXT_GRADIENT } from './const'; import { TextStyle } from './TextStyle'; import { TextMetrics } from './TextMetrics'; @@ -18,11 +15,12 @@ const defaultDestroyOptions: IDestroyOptions = { baseTexture: true, }; -interface ModernContext2D extends CanvasRenderingContext2D { - // for chrome less 94 - textLetterSpacing?: number; - // for chrome greater 94 - letterSpacing?: number; +interface ModernContext2D extends CanvasRenderingContext2D +{ + // for chrome less 94 + textLetterSpacing?: number; + // for chrome greater 94 + letterSpacing?: number; } /** @@ -45,19 +43,10 @@ interface ModernContext2D extends CanvasRenderingContext2D { * ```js * let text = new PIXI.Text('This is a PixiJS text',{fontFamily : 'Arial', fontSize: 24, fill : 0xff1010, align : 'center'}); * ``` - * * @memberof PIXI */ export class Text extends Sprite { - /** - * New behavior for `lineHeight` that's meant to mimic HTML text. A value of `true` will - * make sure the first baseline is offset by the `lineHeight` value if it is greater than `fontSize`. - * A value of `false` will use the legacy behavior and not change the baseline of the first line. - * In the next major release, we'll enable this by default. - */ - public static nextLineHeightBehavior = false; - /** * New rendering behavior for letter-spacing which uses Chrome's new native API. This will * lead to more accurate letter-spacing results because it does not try to manually draw @@ -76,7 +65,6 @@ export class Text extends Sprite * The resolution / device pixel ratio of the canvas. * * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually. - * * @default PIXI.settings.RESOLUTION */ _resolution: number; @@ -84,28 +72,24 @@ export class Text extends Sprite /** * Private tracker for the current text. - * * @private */ protected _text: string; /** * Private tracker for the current font. - * * @private */ protected _font: string; /** * Private tracker for the current style. - * * @private */ protected _style: TextStyle; /** * Private listener to track style changes. - * * @private */ protected _styleListener: () => void; @@ -123,13 +107,13 @@ export class Text extends Sprite * @param {object|PIXI.TextStyle} [style] - The style parameters * @param canvas - The canvas element for drawing text */ - constructor(text: string, style?: Partial|TextStyle, canvas?: HTMLCanvasElement) + constructor(text?: string | number, style?: Partial | TextStyle, canvas?: HTMLCanvasElement) { let ownCanvas = false; if (!canvas) { - canvas = document.createElement('canvas'); + canvas = settings.ADAPTER.createCanvas(); ownCanvas = true; } @@ -145,7 +129,7 @@ export class Text extends Sprite this._ownCanvas = ownCanvas; this.canvas = canvas; - this.context = this.canvas.getContext('2d'); + this.context = canvas.getContext('2d') as CanvasRenderingContext2D; this._resolution = settings.RESOLUTION; this._autoResolution = true; @@ -166,7 +150,6 @@ export class Text extends Sprite * By default this is used internally to ensure the texture is correct before rendering, * but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text, * and then shared across multiple Sprites. - * * @param respectDirty - Whether to abort updating the text if the Text isn't dirty and the function is called. */ public updateText(respectDirty: boolean): void @@ -243,7 +226,9 @@ export class Text extends Sprite context.strokeStyle = 'black'; const dropShadowColor = style.dropShadowColor; - const rgb = hex2rgb(typeof dropShadowColor === 'number' ? dropShadowColor : string2hex(dropShadowColor)); + const rgb = utils.hex2rgb(typeof dropShadowColor === 'number' + ? dropShadowColor + : utils.string2hex(dropShadowColor)); const dropShadowBlur = style.dropShadowBlur * this._resolution; const dropShadowDistance = style.dropShadowDistance * this._resolution; @@ -269,7 +254,7 @@ export class Text extends Sprite let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2; - if (!Text.nextLineHeightBehavior || lineHeight - fontProperties.fontSize < 0) + if (lineHeight - fontProperties.fontSize < 0) { linePositionYShift = 0; } @@ -316,7 +301,6 @@ export class Text extends Sprite /** * Render the text with letter-spacing. - * * @param text - The text to draw * @param x - Horizontal position to draw the text * @param y - Vertical position to draw the text @@ -401,7 +385,7 @@ export class Text extends Sprite if (this._style.trim) { - const trimmed = trimCanvas(canvas); + const trimmed = utils.trimCanvas(canvas); if (trimmed.data) { @@ -431,15 +415,11 @@ export class Text extends Sprite texture.updateUvs(); - // Recursively updates transform of all objects from the root to this one - this._recursivePostUpdateTransform(); - this.dirty = false; } /** * Renders the object using the WebGL renderer - * * @param renderer - The renderer */ protected _render(renderer: Renderer): void @@ -455,13 +435,33 @@ export class Text extends Sprite super._render(renderer); } + /** Updates the transform on all children of this container for rendering. */ + public updateTransform(): void + { + this.updateText(true); + + super.updateTransform(); + } + + public getBounds(skipUpdate?: boolean, rect?: Rectangle): Rectangle + { + this.updateText(true); + + if (this._textureID === -1) + { + // texture was updated: recalculate transforms + skipUpdate = false; + } + + return super.getBounds(skipUpdate, rect); + } + /** * Gets the local bounds of the text object. - * * @param rect - The output rectangle. - * @return The bounds. + * @returns The bounds. */ - public getLocalBounds(rect: Rectangle): Rectangle + public getLocalBounds(rect?: Rectangle): Rectangle { this.updateText(true); @@ -471,7 +471,6 @@ export class Text extends Sprite /** Calculates the bounds of the Text as a rectangle. The bounds calculation takes the worldTransform into account. */ protected _calculateBounds(): void { - this.updateText(true); this.calculateVertices(); // if we have already done this on THIS frame. this._bounds.addQuad(this.vertexData); @@ -479,17 +478,19 @@ export class Text extends Sprite /** * Generates the fill style. Can automatically generate a gradient based on the fill style being an array - * * @param style - The style. * @param lines - The lines of text. - * @return The fill style + * @param metrics + * @returns The fill style */ - private _generateFillStyle(style: TextStyle, lines: string[], metrics: TextMetrics): string|CanvasGradient|CanvasPattern + private _generateFillStyle( + style: TextStyle, lines: string[], metrics: TextMetrics + ): string | CanvasGradient | CanvasPattern { // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as // the setter converts to string. See this thread for more details: // https://github.com/microsoft/TypeScript/issues/2521 - const fillStyle: string|string[]|CanvasGradient|CanvasPattern = style.fill as any; + const fillStyle: string | string[] | CanvasGradient | CanvasPattern = style.fill as any; if (!Array.isArray(fillStyle)) { @@ -502,7 +503,7 @@ export class Text extends Sprite // the gradient will be evenly spaced out according to how large the array is. // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75 - let gradient: string[]|CanvasGradient; + let gradient: string[] | CanvasGradient; // a dropshadow will enlarge the canvas and result in the gradient being // generated with the incorrect dimensions @@ -631,7 +632,6 @@ export class Text extends Sprite * * Note* Unlike a Sprite, a Text object will automatically destroy its baseTexture and texture as * the majority of the time the texture will not be shared with any other Sprites. - * * @param options - Options parameter. A boolean will act as if all options * have been set to that value * @param {boolean} [options.children=false] - if set to true, all the children will have their @@ -639,7 +639,7 @@ export class Text extends Sprite * @param {boolean} [options.texture=true] - Should it destroy the current texture of the sprite as well * @param {boolean} [options.baseTexture=true] - Should it destroy the base texture of the sprite as well */ - public destroy(options?: IDestroyOptions|boolean): void + public destroy(options?: IDestroyOptions | boolean): void { if (typeof options === 'boolean') { @@ -676,7 +676,7 @@ export class Text extends Sprite { this.updateText(true); - const s = sign(this.scale.x) || 1; + const s = utils.sign(this.scale.x) || 1; this.scale.x = s * value / this._texture.orig.width; this._width = value; @@ -694,7 +694,7 @@ export class Text extends Sprite { this.updateText(true); - const s = sign(this.scale.y) || 1; + const s = utils.sign(this.scale.y) || 1; this.scale.y = s * value / this._texture.orig.height; this._height = value; @@ -705,7 +705,7 @@ export class Text extends Sprite * * Set up an event listener to listen for changes on the style object and mark the text as dirty. */ - get style(): TextStyle|Partial + get style(): TextStyle | Partial { // TODO: Can't have different types for getter and setter. The getter shouldn't have the ITextStyle // since the setter creates the TextStyle. See this thread for more details: @@ -713,7 +713,7 @@ export class Text extends Sprite return this._style; } - set style(style: TextStyle|Partial) + set style(style: TextStyle | Partial) { style = style || {}; @@ -736,7 +736,7 @@ export class Text extends Sprite return this._text; } - set text(text: string) + set text(text: string | number) { text = String(text === null || text === undefined ? '' : text); @@ -752,7 +752,6 @@ export class Text extends Sprite * The resolution / device pixel ratio of the canvas. * * This is set to automatically match the renderer resolution by default, but can be overridden by setting manually. - * * @default 1 */ get resolution(): number diff --git a/packages/text/src/TextMetrics.ts b/packages/text/src/TextMetrics.ts index 078ce0af256..e582fddfa46 100644 --- a/packages/text/src/TextMetrics.ts +++ b/packages/text/src/TextMetrics.ts @@ -1,6 +1,8 @@ -import { TextStyle, TextStyleWhiteSpace } from './TextStyle'; +import { settings } from '@pixi/core'; +import type { TextStyle, TextStyleWhiteSpace } from './TextStyle'; -interface IFontMetrics { +interface IFontMetrics +{ ascent: number; descent: number; fontSize: number; @@ -15,7 +17,6 @@ type CharacterWidthCache = { [key: string]: number }; * let style = new PIXI.TextStyle({fontFamily : 'Arial', fontSize: 24, fill : 0xff1010, align : 'center'}) * let textMetrics = PIXI.TextMetrics.measureText('Your text', style) * ``` - * * @memberof PIXI */ export class TextMetrics @@ -46,7 +47,6 @@ export class TextMetrics /** * The font properties object from TextMetrics.measureFont. - * * @type {PIXI.IFontMetrics} */ public fontProperties: IFontMetrics; @@ -56,9 +56,10 @@ export class TextMetrics public static BASELINE_MULTIPLIER: number; public static HEIGHT_MULTIPLIER: number; + private static __canvas: HTMLCanvasElement | OffscreenCanvas; + private static __context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; + // TODO: These should be protected but they're initialized outside of the class. - public static _canvas: HTMLCanvasElement|OffscreenCanvas; - public static _context: CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D; public static _fonts: { [font: string]: IFontMetrics }; public static _newlines: number[]; public static _breakingSpaces: number[]; @@ -90,12 +91,11 @@ export class TextMetrics /** * Measures the supplied string of text and returns a Rectangle. - * * @param text - The text to measure. * @param style - The text style to use for measuring * @param wordWrap - Override for if word-wrap should be applied to the text. * @param canvas - optional specification of the canvas to use for measuring. - * @return Measured width and height of the text. + * @returns Measured width and height of the text. */ public static measureText( text: string, @@ -164,11 +164,10 @@ export class TextMetrics /** * Applies newlines to a string to have it optimally fit into the horizontal * bounds set by the Text object's wordWrapWidth property. - * * @param text - String to apply word wrapping to * @param style - the style to use when wrapping * @param canvas - optional specification of the canvas to use for measuring. - * @return New string with new lines applied where required + * @returns New string with new lines applied where required */ private static wordWrap( text: string, @@ -363,10 +362,9 @@ export class TextMetrics /** * Convienience function for logging each line added during the wordWrap method. - * * @param line - The line of text to add * @param newLine - Add new line character to end - * @return A formatted line + * @returns A formatted line */ private static addLine(line: string, newLine = true): string { @@ -379,15 +377,14 @@ export class TextMetrics /** * Gets & sets the widths of calculated characters in a cache object - * * @param key - The key * @param letterSpacing - The letter spacing * @param cache - The cache * @param context - The canvas context - * @return The from cache. + * @returns The from cache. */ private static getFromCache(key: string, letterSpacing: number, cache: CharacterWidthCache, - context: CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D): number + context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): number { let width = cache[key]; @@ -404,9 +401,8 @@ export class TextMetrics /** * Determines whether we should collapse breaking spaces. - * * @param whiteSpace - The TextStyle property whiteSpace - * @return Should collapse + * @returns Should collapse */ private static collapseSpaces(whiteSpace: TextStyleWhiteSpace): boolean { @@ -415,9 +411,8 @@ export class TextMetrics /** * Determines whether we should collapse newLine chars. - * * @param whiteSpace - The white space - * @return should collapse + * @returns should collapse */ private static collapseNewlines(whiteSpace: TextStyleWhiteSpace): boolean { @@ -426,9 +421,8 @@ export class TextMetrics /** * Trims breaking whitespaces from string. - * * @param text - The text - * @return Trimmed string + * @returns Trimmed string */ private static trimRight(text: string): string { @@ -454,9 +448,8 @@ export class TextMetrics /** * Determines if char is a newline. - * * @param char - The character - * @return True if newline, False otherwise. + * @returns True if newline, False otherwise. */ private static isNewline(char: string): boolean { @@ -465,7 +458,7 @@ export class TextMetrics return false; } - return (TextMetrics._newlines.indexOf(char.charCodeAt(0)) >= 0); + return TextMetrics._newlines.includes(char.charCodeAt(0)); } /** @@ -474,10 +467,9 @@ export class TextMetrics * It allows one to determine whether char should be a breaking whitespace * For example certain characters in CJK langs or numbers. * It must return a boolean. - * - * @param char - The character - * @param [nextChar] - The next character - * @return True if whitespace, False otherwise. + * @param char - The character + * @param [_nextChar] - The next character + * @returns True if whitespace, False otherwise. */ static isBreakingSpace(char: string, _nextChar?: string): boolean { @@ -486,14 +478,13 @@ export class TextMetrics return false; } - return (TextMetrics._breakingSpaces.indexOf(char.charCodeAt(0)) >= 0); + return TextMetrics._breakingSpaces.includes(char.charCodeAt(0)); } /** * Splits a string into words, breaking-spaces and newLine characters - * * @param text - The text - * @return A tokenized array + * @returns A tokenized array */ private static tokenize(text: string): string[] { @@ -540,10 +531,9 @@ export class TextMetrics * It allows one to customise which words should break * Examples are if the token is CJK or numbers. * It must return a boolean. - * - * @param token - The token + * @param _token - The token * @param breakWords - The style attr break words - * @return Whether to break word or not + * @returns Whether to break word or not */ static canBreakWords(_token: string, breakWords: boolean): boolean { @@ -557,13 +547,12 @@ export class TextMetrics * should be broken by newlines * For example certain characters in CJK langs or numbers. * It must return a boolean. - * - * @param char - The character - * @param nextChar - The next character - * @param token - The token/word the characters are from - * @param index - The index in the token of the char - * @param breakWords - The style attr break words - * @return whether to break word or not + * @param _char - The character + * @param _nextChar - The next character + * @param _token - The token/word the characters are from + * @param _index - The index in the token of the char + * @param _breakWords - The style attr break words + * @returns whether to break word or not */ static canBreakChars(_char: string, _nextChar: string, _token: string, _index: number, _breakWords: boolean): boolean @@ -577,13 +566,11 @@ export class TextMetrics * It is called when a token (usually a word) has to be split into separate pieces * in order to determine the point to break a word. * It must return an array of characters. - * * @example * // Correctly splits emojis, eg "🤪🤪" will result in two element array, each with one emoji. * TextMetrics.wordWrapSplit = (token) => [...token]; - * * @param token - The token to split - * @return The characters of the token + * @returns The characters of the token */ static wordWrapSplit(token: string): string[] { @@ -592,9 +579,8 @@ export class TextMetrics /** * Calculates the ascent, descent and fontSize of a given font-style - * * @param font - String representing the style of the font - * @return Font properties object + * @returns Font properties object */ public static measureFont(font: string): IFontMetrics { @@ -700,7 +686,6 @@ export class TextMetrics /** * Clear font metrics in metrics cache. - * * @param {string} [font] - font name. If font name not set then clear cache for all fonts. */ public static clearMetrics(font = ''): void @@ -714,65 +699,73 @@ export class TextMetrics TextMetrics._fonts = {}; } } -} -/** - * Internal return object for {@link PIXI.TextMetrics.measureFont `TextMetrics.measureFont`}. - * - * @typedef {object} FontMetrics - * @property {number} ascent - The ascent distance - * @property {number} descent - The descent distance - * @property {number} fontSize - Font size from ascent to descent - * @memberof PIXI.TextMetrics - * @private - */ - -const canvas = ((): HTMLCanvasElement|OffscreenCanvas => -{ - try + /** + * Cached canvas element for measuring text + * TODO: this should be private, but isn't because of backward compat, will fix later. + * @ignore + */ + public static get _canvas(): HTMLCanvasElement | OffscreenCanvas { - // OffscreenCanvas2D measureText can be up to 40% faster. - const c = new OffscreenCanvas(0, 0); - const context = c.getContext('2d'); - - if (context && context.measureText) + if (!TextMetrics.__canvas) { - return c; + let canvas: HTMLCanvasElement | OffscreenCanvas; + + try + { + // OffscreenCanvas2D measureText can be up to 40% faster. + const c = new OffscreenCanvas(0, 0); + const context = c.getContext('2d'); + + if (context?.measureText) + { + TextMetrics.__canvas = c; + + return c; + } + + canvas = settings.ADAPTER.createCanvas(); + } + catch (ex) + { + canvas = settings.ADAPTER.createCanvas(); + } + canvas.width = canvas.height = 10; + TextMetrics.__canvas = canvas; } - return document.createElement('canvas'); + return TextMetrics.__canvas; } - catch (ex) - { - return document.createElement('canvas'); - } -})(); -canvas.width = canvas.height = 10; + /** + * TODO: this should be private, but isn't because of backward compat, will fix later. + * @ignore + */ + public static get _context(): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D + { + if (!TextMetrics.__context) + { + TextMetrics.__context = TextMetrics._canvas.getContext('2d'); + } -/** - * Cached canvas element for measuring text - * - * @memberof PIXI.TextMetrics - * @type {HTMLCanvasElement} - * @private - */ -TextMetrics._canvas = canvas; + return TextMetrics.__context; + } +} /** - * Cache for context to use. - * + * Internal return object for {@link PIXI.TextMetrics.measureFont `TextMetrics.measureFont`}. + * @typedef {object} FontMetrics + * @property {number} ascent - The ascent distance + * @property {number} descent - The descent distance + * @property {number} fontSize - Font size from ascent to descent * @memberof PIXI.TextMetrics - * @type {CanvasRenderingContext2D} * @private */ -TextMetrics._context = canvas.getContext('2d'); /** * Cache of {@see PIXI.TextMetrics.FontMetrics} objects. - * * @memberof PIXI.TextMetrics - * @type {Object} + * @type {object} * @private */ TextMetrics._fonts = {}; @@ -780,7 +773,6 @@ TextMetrics._fonts = {}; /** * String used for calculate font metrics. * These characters are all tall to help calculate the height required for text. - * * @static * @memberof PIXI.TextMetrics * @name METRICS_STRING @@ -791,7 +783,6 @@ TextMetrics.METRICS_STRING = '|ÉqÅ'; /** * Baseline symbol for calculate font metrics. - * * @static * @memberof PIXI.TextMetrics * @name BASELINE_SYMBOL @@ -802,7 +793,6 @@ TextMetrics.BASELINE_SYMBOL = 'M'; /** * Baseline multiplier for calculate font metrics. - * * @static * @memberof PIXI.TextMetrics * @name BASELINE_MULTIPLIER @@ -813,7 +803,6 @@ TextMetrics.BASELINE_MULTIPLIER = 1.4; /** * Height multiplier for setting height of canvas to calculate font metrics. - * * @static * @memberof PIXI.TextMetrics * @name HEIGHT_MULTIPLIER @@ -824,7 +813,6 @@ TextMetrics.HEIGHT_MULTIPLIER = 2.0; /** * Cache of new line chars. - * * @memberof PIXI.TextMetrics * @type {number[]} * @private @@ -836,7 +824,6 @@ TextMetrics._newlines = [ /** * Cache of breaking spaces. - * * @memberof PIXI.TextMetrics * @type {number[]} * @private @@ -860,7 +847,6 @@ TextMetrics._breakingSpaces = [ /** * A number, or a string containing a number. - * * @memberof PIXI * @typedef {object} IFontMetrics * @property {number} ascent - Font ascent diff --git a/packages/text/src/TextStyle.ts b/packages/text/src/TextStyle.ts index bba2a009d14..ce746bb4ac0 100644 --- a/packages/text/src/TextStyle.ts +++ b/packages/text/src/TextStyle.ts @@ -2,7 +2,7 @@ /* eslint-disable */ import { TEXT_GRADIENT } from './const'; -import { hex2string } from '@pixi/utils'; +import { utils } from '@pixi/core'; export type TextStyleAlign = 'left'|'center'|'right'|'justify'; export type TextStyleFill = string|string[]|number|number[]|CanvasGradient|CanvasPattern; @@ -719,7 +719,7 @@ export class TextStyle implements ITextStyle let fontFamily = fontFamilies[i].trim(); // Check if font already contains strings - if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily) && genericFontFamilies.indexOf(fontFamily) < 0) + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily)) { fontFamily = `"${fontFamily}"`; } @@ -740,11 +740,11 @@ function getSingleColor(color: string|number): string { if (typeof color === 'number') { - return hex2string(color); + return utils.hex2string(color); } else if (typeof color === 'string') { - if ( color.indexOf('0x') === 0 ) + if ( color.startsWith('0x')) { color = color.replace('0x', '#'); } diff --git a/packages/text/src/const.ts b/packages/text/src/const.ts index 028a90055f5..a842a437361 100644 --- a/packages/text/src/const.ts +++ b/packages/text/src/const.ts @@ -1,6 +1,5 @@ /** * Constants that define the type of gradient on text. - * * @static * @constant * @name TEXT_GRADIENT @@ -9,7 +8,9 @@ * @property {number} LINEAR_VERTICAL Vertical gradient * @property {number} LINEAR_HORIZONTAL Linear gradient */ -export enum TEXT_GRADIENT { +export enum TEXT_GRADIENT +// eslint-disable-next-line @typescript-eslint/indent +{ LINEAR_VERTICAL = 0, LINEAR_HORIZONTAL = 1 } diff --git a/packages/text/test/Text.tests.ts b/packages/text/test/Text.tests.ts index 3521df06631..102ee72f3d5 100644 --- a/packages/text/test/Text.tests.ts +++ b/packages/text/test/Text.tests.ts @@ -1,81 +1,77 @@ import { Text } from '@pixi/text'; import { Sprite } from '@pixi/sprite'; -import { skipHello } from '@pixi/utils'; -import { settings } from '@pixi/settings'; -import { Renderer, BatchRenderer } from '@pixi/core'; -import { expect } from 'chai'; +import { settings, Renderer, utils } from '@pixi/core'; +import type { IDestroyOptions } from '@pixi/display'; -skipHello(); +utils.skipHello(); -Renderer.registerPlugin('batch', BatchRenderer); - -describe('Text', function () +describe('Text', () => { - describe('properties', function () + describe('properties', () => { - it('should modify the height of the object when setting height', function () + it('should modify the height of the object when setting height', () => { const text = new Text('foo'); text.height = 300; - expect(text.height).to.equal(300); + expect(text.height).toEqual(300); }); - it('should modify the width of the object when setting width', function () + it('should modify the width of the object when setting width', () => { const text = new Text('foo'); text.width = 300; - expect(text.width).to.equal(300); + expect(text.width).toEqual(300); }); - it('should set the text resolution to match the resolution setting when constructed time', function () + it('should set the text resolution to match the resolution setting when constructed time', () => { const text = new Text('foo'); - expect(text.resolution).to.equal(settings.RESOLUTION); + expect(text.resolution).toEqual(settings.RESOLUTION); }); - it('should update the text resolution to match the renderer resolution when being rendered to screen', function () + it('should update the text resolution to match the renderer resolution when being rendered to screen', () => { const text = new Text('foo'); - expect(text.resolution).to.equal(settings.RESOLUTION); + expect(text.resolution).toEqual(settings.RESOLUTION); const renderer = new Renderer({ resolution: 2 }); - expect(renderer.resolution).to.equal(2); + expect(renderer.resolution).toEqual(2); renderer.render(text); - expect(text.resolution).to.equal(renderer.resolution); + expect(text.resolution).toEqual(renderer.resolution); renderer.destroy(); }); - it('should use any manually set text resolution over the renderer resolution', function () + it('should use any manually set text resolution over the renderer resolution', () => { const text = new Text('foo'); text.resolution = 3; - expect(text.resolution).to.equal(3); + expect(text.resolution).toEqual(3); const renderer = new Renderer({ resolution: 2 }); renderer.render(text); - expect(text.resolution).to.equal(3); + expect(text.resolution).toEqual(3); renderer.destroy(); }); }); - describe('destroy', function () + describe('destroy', () => { - it('should now clear canvas size on imported canvas', function () + it('should now clear canvas size on imported canvas', () => { const canvas = document.createElement('canvas'); const text = new Text('blah', {}, canvas); @@ -83,134 +79,134 @@ describe('Text', function () text.destroy(); - expect(canvas.width).to.equal(width); - expect(canvas.height).to.equal(height); + expect(canvas.width).toEqual(width); + expect(canvas.height).toEqual(height); }); - it('should clear size on owned canvas during destroy', function () + it('should clear size on owned canvas during destroy', () => { const text = new Text('blah', {}); const { canvas } = text; text.destroy(); - expect(canvas.width).to.equal(0); - expect(canvas.height).to.equal(0); + expect(canvas.width).toEqual(0); + expect(canvas.height).toEqual(0); }); - it('should call through to Sprite.destroy', function () + it('should call through to Sprite.destroy', () => { const text = new Text('foo'); - expect(text.anchor).to.not.equal(null); + expect(text.anchor).not.toEqual(null); text.destroy(); - expect(text.anchor).to.equal(null); + expect(text.anchor).toEqual(null); }); - it('should set context to null', function () + it('should set context to null', () => { const text = new Text('foo'); - expect(text.style).to.not.equal(null); + expect(text.style).not.toEqual(null); text.destroy(); - expect(text.style).to.equal(null); + expect(text.style).toEqual(null); }); - it('should destroy children if children flag is set', function () + it('should destroy children if children flag is set', () => { const text = new Text('foo'); const child = new Sprite(); text.addChild(child); text.destroy({ children: true }); - expect(text.transform).to.equal(null); - expect(child.transform).to.equal(null); + expect(text.transform).toEqual(null); + expect(child.transform).toEqual(null); }); - it('should accept options correctly', function () + it('should accept options correctly', () => { const text = new Text('foo'); const child = new Sprite(); text.addChild(child); text.destroy(true); - expect(text.transform).to.equal(null); - expect(child.transform).to.equal(null); + expect(text.transform).toEqual(null); + expect(child.transform).toEqual(null); }); - it('should pass opts on to children if children flag is set', function () + it('should pass opts on to children if children flag is set', () => { const text = new Text('foo'); const child = new Sprite(); - let childDestroyOpts; + let childDestroyOpts: IDestroyOptions | boolean; - child.destroy = function (opts) + child.destroy = (opts) => { childDestroyOpts = opts; }; text.addChild(child); text.destroy({ children: true, texture: true }); - expect(childDestroyOpts).to.deep.equal({ children: true, texture: true, baseTexture: true }); + expect(childDestroyOpts).toEqual({ children: true, texture: true, baseTexture: true }); }); }); - describe('text', function () + describe('text', () => { - it('should convert numbers into strings', function () + it('should convert numbers into strings', () => { const text = new Text(2); - expect(text.text).to.equal('2'); + expect(text.text).toEqual('2'); }); - it('should not change 0 to \'\'', function () + it('should not change 0 to \'\'', () => { const text = new Text(0); - expect(text.text).to.equal('0'); + expect(text.text).toEqual('0'); }); - it('should prevent setting null', function () + it('should prevent setting null', () => { const text = new Text(null); - expect(text.text).to.equal(''); + expect(text.text).toEqual(''); }); - it('should prevent setting undefined', function () + it('should prevent setting undefined', () => { const text = new Text(); - expect(text.text).to.equal(''); + expect(text.text).toEqual(''); }); - it('should trim an empty string', function () + it('should trim an empty string', () => { const text = new Text('', { trim: true }); - expect(text.text).to.equal(''); + expect(text.text).toEqual(''); }); - it('should allow setting \'\' for v5', function () + it('should allow setting \'\' for v5', () => { const text = new Text(''); - expect(text.text).to.equal(''); + expect(text.text).toEqual(''); }); - it('should keep at least 1 pixel for canvas width and height', function () + it('should keep at least 1 pixel for canvas width and height', () => { const text = new Text(''); - text.updateText(); + text.updateText(undefined); - expect(text.canvas.width).to.be.above(1); - expect(text.canvas.height).to.be.above(1); + expect(text.canvas.width).toBeGreaterThan(1); + expect(text.canvas.height).toBeGreaterThan(1); text.text = '\n'; - expect(text.canvas.width).to.be.above(0); + expect(text.canvas.width).toBeGreaterThan(0); }); }); }); diff --git a/packages/text/test/TextMetrics.tests.ts b/packages/text/test/TextMetrics.tests.ts index 25dbf9885f4..20b8c7451f1 100644 --- a/packages/text/test/TextMetrics.tests.ts +++ b/packages/text/test/TextMetrics.tests.ts @@ -1,5 +1,5 @@ +import type { ITextStyle } from '@pixi/text'; import { TextMetrics, TextStyle } from '@pixi/text'; -import { expect } from 'chai'; /** * Fonts render slightly differently between platforms so tests that depend on a specific @@ -44,7 +44,7 @@ const breakingSpaces = [ '\u3000', ]; -describe('TextMetrics', function () +describe('TextMetrics', () => { const defaultStyle = { breakWords: true, @@ -52,47 +52,49 @@ describe('TextMetrics', function () fontSize: 20, fontStyle: 'italic', fontVariant: 'normal', - fontWeight: 900, + fontWeight: '900', wordWrap: true, wordWrapWidth: 200, letterSpacing: 4, - }; + } as Partial; - describe('wordWrap without breakWords', function () + describe('wordWrap without breakWords', () => { - it('width should not be greater than wordWrapWidth with longText', function () + it('width should not be greater than wordWrapWidth with longText', () => { // On Windows 'exercitationem' renders to about 217px, bigger wrap width required for this test to be valid on every platform - const style = Object.assign({}, defaultStyle, { wordWrapWidth: 220, breakWords: false }); + const style = Object.assign({}, defaultStyle, { wordWrapWidth: 220, breakWords: false }) as Partial; const metrics = TextMetrics.measureText(longText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line).to.not.contain(' ', 'should not have multiple spaces in a row'); - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line).toEqual( + expect.not.arrayContaining([' ', 'should not have multiple spaces in a row']) + ); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('width should be greater than wordWrapWidth with breakingWordText', function () + it('width should be greater than wordWrapWidth with breakingWordText', () => { const style = Object.assign({}, defaultStyle, { breakWords: false }); const metrics = TextMetrics.measureText(breakingWordText, new TextStyle(style)); - expect(metrics.width).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeGreaterThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('width should be within a character width from wordWrapWidth with fillText', function () + it('width should be within a character width from wordWrapWidth with fillText', () => { const charWidth = 4; // it should fill the line to at lease width -4 @@ -100,81 +102,81 @@ describe('TextMetrics', function () const metrics = TextMetrics.measureText(fillText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); - expect(metrics.width + charWidth).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); + expect(metrics.width + charWidth).toBeGreaterThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('width should be greater than wordWrapWidth and should format correct spaces', function () + it('width should be greater than wordWrapWidth and should format correct spaces', () => { const style = Object.assign({}, defaultStyle, { breakWords: false }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeGreaterThan(style.wordWrapWidth); - expect(metrics.lines[0][0]).to.equal(' ', '1st line should start with a space'); - expect(metrics.lines[4][0]).to.equal(' ', '5th line should start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal(' ', '5th line should start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal(' ', '5th line should start with 3 spaces (3)'); - expect(metrics.lines[4][3]).to.not.equal(' ', '5th line should not have a space as the 4th char'); + expect(metrics.lines[0][0]).toEqual(' '); + expect(metrics.lines[4][0]).toEqual(' '); + expect(metrics.lines[4][1]).toEqual(' '); + expect(metrics.lines[4][2]).toEqual(' '); + expect(metrics.lines[4][3]).not.toEqual(' '); metrics.lines.forEach((line, i) => { if (i !== 0 && i !== 4) { - expect(metrics.lines[1][0]).to.not.equal(' ', 'all lines except 1 & 5 should not have space at the start'); + expect(metrics.lines[1][0]).not.toEqual(' '); } - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('should be able to override wordWrap to false in measureText', function () + it('should be able to override wordWrap to false in measureText', () => { const metrics = TextMetrics.measureText(longText, new TextStyle(defaultStyle), false); - expect(metrics.lines.length).to.equal(1); + expect(metrics.lines.length).toEqual(1); }); }); - describe('wordWrap with breakWords', function () + describe('wordWrap with breakWords', () => { - it('width should not be greater than wordWrapWidth with longText', function () + it('width should not be greater than wordWrapWidth with longText', () => { const style = Object.assign({}, defaultStyle, { breakWords: true }); const metrics = TextMetrics.measureText(longText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('width should not be greater than wordWrapWidth with breakingWordAtStartText', function () + it('width should not be greater than wordWrapWidth with breakingWordAtStartText', () => { const style = Object.assign({}, defaultStyle, { breakWords: true }); const metrics = TextMetrics.measureText(breakingWordText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('width should be within a character width from wordWrapWidth with fillText', function () + it('width should be within a character width from wordWrapWidth with fillText', () => { const charWidth = 4; // it should fill the line to at lease width -4 @@ -182,17 +184,17 @@ describe('TextMetrics', function () const metrics = TextMetrics.measureText(fillText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); - expect(metrics.width + charWidth).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); + expect(metrics.width + charWidth).toBeGreaterThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'should not have space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); - it('no words or characters should lost or changed', function () + it('no words or characters should lost or changed', () => { const style = Object.assign({}, defaultStyle, { breakWords: true }); @@ -200,39 +202,39 @@ describe('TextMetrics', function () const lines = metrics.lines.reduce((accumulator, line) => accumulator + line); - expect(lines).to.equal(intergityText, 'should have the same chars as the original text'); + expect(lines).toEqual(intergityText); }); - it('width should not be greater than wordWrapWidth and should format correct spaces', function () + it('width should not be greater than wordWrapWidth and should format correct spaces', () => { const style = Object.assign({}, defaultStyle, { breakWords: true }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); - expect(metrics.lines[0][0]).to.equal(' ', '1st line should start with a space'); - expect(metrics.lines[4][0]).to.equal(' ', '5th line should start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal(' ', '5th line should start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal(' ', '5th line should start with 3 spaces (3)'); - expect(metrics.lines[4][3]).to.not.equal(' ', '5th line should not have a space as the 4th char'); + expect(metrics.lines[0][0]).toEqual(' '); + expect(metrics.lines[4][0]).toEqual(' '); + expect(metrics.lines[4][1]).toEqual(' '); + expect(metrics.lines[4][2]).toEqual(' '); + expect(metrics.lines[4][3]).not.toEqual(' '); metrics.lines.forEach((line, i) => { if (i !== 0 && i !== 4) { - expect(metrics.lines[1][0]).to.not.equal(' ', 'all lines except 1 & 5 should not have space at the start'); + expect(metrics.lines[1][0]).not.toEqual(' '); } - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line[line.length - 1]).not.toEqual(' '); }); }); }); - describe('wordWrap misc', function () + describe('wordWrap misc', () => { const originalSplit = TextMetrics.wordWrapSplit; - afterEach(function () + afterEach(() => { TextMetrics.wordWrapSplit = originalSplit; }); @@ -244,41 +246,44 @@ describe('TextMetrics', function () TextMetrics.wordWrapSplit = (token) => { wasSplitCalled = true; - expect(token).to.equal('testword1234567890abcd!'); + expect(token).toEqual('testword1234567890abcd!'); return ['s', 'p', 'l', 'i', 't']; }; - const brokenText = TextMetrics.wordWrap('testword1234567890abcd!', new TextStyle(defaultStyle)); + const brokenText = TextMetrics['wordWrap']('testword1234567890abcd!', new TextStyle(defaultStyle)); - expect(wasSplitCalled).to.equal(true); - expect(brokenText).to.equal('split'); + expect(wasSplitCalled).toEqual(true); + expect(brokenText).toEqual('split'); }); }); - describe('whiteSpace `normal` without breakWords', function () + describe('whiteSpace `normal` without breakWords', () => { - it('multiple spaces should be collapsed to 1 and but not newlines', function () + it('multiple spaces should be collapsed to 1 and but not newlines', () => { const style = Object.assign({}, defaultStyle, { breakWords: false, whiteSpace: 'normal' }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeGreaterThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line).to.not.contain(' ', 'should not have multiple spaces in a row'); - expect(line[0]).to.not.equal(' ', 'all lines should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line).toEqual( + expect.not.arrayContaining([' ', 'should not have multiple spaces in a row']) + ); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); + // eslint-disable-next-line func-names it('text is wrapped in a platform-specific way', function () { if (process.platform === 'win32') { - this.skip(); + return; return; } @@ -287,61 +292,64 @@ describe('TextMetrics', function () const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.lines[0][0]).to.equal('S', '1st line should not start with a space'); - expect(metrics.lines[4][0]).to.equal('m', '5th line should not start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal('o', '5th line should not start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal('r', '5th line should not start with 3 spaces (3)'); - expect(metrics.lines[17][0]).to.equal('a', '17th line should not have wrapped'); + expect(metrics.lines[0][0]).toEqual('S'); + expect(metrics.lines[4][0]).toEqual('m'); + expect(metrics.lines[4][1]).toEqual('o'); + expect(metrics.lines[4][2]).toEqual('r'); + expect(metrics.lines[17][0]).toEqual('a'); }); }); - describe('whiteSpace `pre-line` without breakWords', function () + describe('whiteSpace `pre-line` without breakWords', () => { - it('multiple spaces should be collapsed to 1 but not newlines', function () + it('multiple spaces should be collapsed to 1 but not newlines', () => { const style = Object.assign({}, defaultStyle, { breakWords: false, whiteSpace: 'pre-line' }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.above(style.wordWrapWidth); + expect(metrics.width).toBeGreaterThan(style.wordWrapWidth); - expect(metrics.lines[0][0]).to.equal('S', '1st line should not start with a space'); - expect(metrics.lines[4][0]).to.equal('A', '5th line should not start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal('n', '5th line should not start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal('d', '5th line should not start with 3 spaces (3)'); - expect(metrics.lines[17][0]).to.equal('t', '17th line should have wrapped'); + expect(metrics.lines[0][0]).toEqual('S'); + expect(metrics.lines[4][0]).toEqual('A'); + expect(metrics.lines[4][1]).toEqual('n'); + expect(metrics.lines[4][2]).toEqual('d'); + expect(metrics.lines[17][0]).toEqual('t'); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'all lines should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); }); - describe('whiteSpace `normal` with breakWords', function () + describe('whiteSpace `normal` with breakWords', () => { - it('multiple spaces should be collapsed to 1 and but not newlines', function () + it('multiple spaces should be collapsed to 1 and but not newlines', () => { const style = Object.assign({}, defaultStyle, { breakWords: true, whiteSpace: 'normal' }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); metrics.lines.forEach((line) => { - expect(line).to.not.contain(' ', 'should not have multiple spaces in a row'); - expect(line[0]).to.not.equal(' ', 'all lines should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line).toEqual( + expect.not.arrayContaining([' ', 'should not have multiple spaces in a row']) + ); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); + // eslint-disable-next-line func-names it('text is wrapped in a platform-specific way', function () { if (process.platform === 'win32') { - this.skip(); + return; return; } @@ -350,151 +358,154 @@ describe('TextMetrics', function () const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.lines[0][0]).to.equal('S', '1st line should not start with a space'); - expect(metrics.lines[4][0]).to.equal('m', '5th line should not start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal('o', '5th line should not start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal('r', '5th line should not start with 3 spaces (3)'); - expect(metrics.lines[17][0]).to.equal('a', '17th line should not have wrapped'); + expect(metrics.lines[0][0]).toEqual('S'); + expect(metrics.lines[4][0]).toEqual('m'); + expect(metrics.lines[4][1]).toEqual('o'); + expect(metrics.lines[4][2]).toEqual('r'); + expect(metrics.lines[17][0]).toEqual('a'); }); }); - describe('whiteSpace `pre-line` with breakWords', function () + describe('whiteSpace `pre-line` with breakWords', () => { - it('multiple spaces should be collapsed to 1 but not newlines', function () + it('multiple spaces should be collapsed to 1 but not newlines', () => { const style = Object.assign({}, defaultStyle, { breakWords: true, whiteSpace: 'pre-line' }); const metrics = TextMetrics.measureText(spaceNewLineText, new TextStyle(style)); - expect(metrics.width).to.be.below(style.wordWrapWidth); + expect(metrics.width).toBeLessThan(style.wordWrapWidth); - expect(metrics.lines[0][0]).to.equal('S', '1st line should not start with a space'); - expect(metrics.lines[4][0]).to.equal('A', '5th line should not start with 3 spaces (1)'); - expect(metrics.lines[4][1]).to.equal('n', '5th line should not start with 3 spaces (2)'); - expect(metrics.lines[4][2]).to.equal('d', '5th line should not start with 3 spaces (3)'); - expect(metrics.lines[17][0]).to.equal('t', '17th line should have wrapped'); + expect(metrics.lines[0][0]).toEqual('S'); + expect(metrics.lines[4][0]).toEqual('A'); + expect(metrics.lines[4][1]).toEqual('n'); + expect(metrics.lines[4][2]).toEqual('d'); + expect(metrics.lines[17][0]).toEqual('t'); metrics.lines.forEach((line) => { - expect(line[0]).to.not.equal(' ', 'all lines should not have space at the start'); - expect(line[line - 1]).to.not.equal(' ', 'no lines should have a space at the end'); + expect(line[0]).not.toEqual(' '); + expect(line[line.length - 1]).not.toEqual(' '); }); }); }); - describe('trimRight', function () + describe('trimRight', () => { - it('string with no whitespaces to trim', function () + it('string with no whitespaces to trim', () => { - const text = TextMetrics.trimRight('remove white spaces to the right'); + const text = TextMetrics['trimRight']('remove white spaces to the right'); - expect(text).to.equal('remove white spaces to the right'); + expect(text).toEqual('remove white spaces to the right'); }); - it('string with whitespaces to trim', function () + it('string with whitespaces to trim', () => { - const text = TextMetrics.trimRight('remove white spaces to the right '); + const text = TextMetrics['trimRight']('remove white spaces to the right '); - expect(text).to.equal('remove white spaces to the right'); + expect(text).toEqual('remove white spaces to the right'); }); - it('string with strange unicode whitespaces to trim', function () + it('string with strange unicode whitespaces to trim', () => { - const text = TextMetrics.trimRight('remove white spaces to the right\u0009\u0020\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200A\u205F\u3000'); + const text = TextMetrics['trimRight']('remove white spaces to the right\u0009\u0020\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2008\u2009\u200A\u205F\u3000'); - expect(text).to.equal('remove white spaces to the right'); + expect(text).toEqual('remove white spaces to the right'); }); - it('empty string', function () + it('empty string', () => { - const text = TextMetrics.trimRight(''); + const text = TextMetrics['trimRight'](''); - expect(text).to.equal(''); + expect(text).toEqual(''); }); - it('non-string input', function () + it('non-string input', () => { - const text = TextMetrics.trimRight({}); + // @ts-expect-error - should return false on non-string input + const text = TextMetrics['trimRight']({}); - expect(text).to.equal(''); + expect(text).toEqual(''); }); }); - describe('isNewline', function () + describe('isNewline', () => { - it('line feed', function () + it('line feed', () => { - const bool = TextMetrics.isNewline('\n'); + const bool = TextMetrics['isNewline']('\n'); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('carriage return', function () + it('carriage return', () => { - const bool = TextMetrics.isNewline('\r'); + const bool = TextMetrics['isNewline']('\r'); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('newline char', function () + it('newline char', () => { - const bool = TextMetrics.isNewline('A'); + const bool = TextMetrics['isNewline']('A'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('non string', function () + it('non string', () => { - const bool = TextMetrics.isNewline({}); + // @ts-expect-error - should return false on non-string input + const bool = TextMetrics['isNewline']({}); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); }); - describe('isBreakingSpace', function () + describe('isBreakingSpace', () => { - it('legit breaking spaces', function () + it('legit breaking spaces', () => { breakingSpaces.forEach((char) => { const bool = TextMetrics.isBreakingSpace(char); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); }); - it('non breaking spaces', function () + it('non breaking spaces', () => { nonBreakingSpaces.forEach((char) => { const bool = TextMetrics.isBreakingSpace(char); - expect(bool).to.not.equal(true); + expect(bool).not.toEqual(true); }); }); - it('newline char', function () + it('newline char', () => { const bool = TextMetrics.isBreakingSpace('A'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('non string', function () + it('non string', () => { + // @ts-expect-error - should return false on non-string input const bool = TextMetrics.isBreakingSpace({}); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('overridable breaking spaces', function () + it('overridable breaking spaces', () => { const reg = /[あいうえお]/; const original = TextMetrics.isBreakingSpace; // override breakingSpace - TextMetrics.isBreakingSpace = function (char, nextChar) + TextMetrics.isBreakingSpace = (char, nextChar) => { const isBreakingSpace = breakingSpaces.includes(char); @@ -510,7 +521,7 @@ describe('TextMetrics', function () { const bool = TextMetrics.isBreakingSpace(char, 'あ'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); // reset the override breakingSpace @@ -518,169 +529,175 @@ describe('TextMetrics', function () }); }); - describe('tokenize', function () + describe('tokenize', () => { - it('full example', function () + it('full example', () => { - const arr = TextMetrics.tokenize(spaceNewLineText); + const arr = TextMetrics['tokenize'](spaceNewLineText); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(146); - expect(arr).to.not.contain(''); - expect(arr).to.not.contain(null); + expect(arr).toBeArray(); + expect(arr.length).toEqual(146); + expect(arr).toEqual(expect.not.arrayContaining([''])); + expect(arr).toEqual(expect.not.arrayContaining([null])); }); - it('empty string', function () + it('empty string', () => { - const arr = TextMetrics.tokenize(''); + const arr = TextMetrics['tokenize'](''); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(0); + expect(arr).toBeArray(); + expect(arr.length).toEqual(0); }); - it('single char', function () + it('single char', () => { - const arr = TextMetrics.tokenize('A'); + const arr = TextMetrics['tokenize']('A'); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(1); + expect(arr).toBeArray(); + expect(arr.length).toEqual(1); }); - it('newline char', function () + it('newline char', () => { - const arr = TextMetrics.tokenize('\n'); + const arr = TextMetrics['tokenize']('\n'); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(1); + expect(arr).toBeArray(); + expect(arr.length).toEqual(1); }); - it('breakingSpaces', function () + it('breakingSpaces', () => { - const arr = TextMetrics.tokenize(breakingSpaces.join('')); + const arr = TextMetrics['tokenize'](breakingSpaces.join('')); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(breakingSpaces.length); + expect(arr).toBeArray(); + expect(arr.length).toEqual(breakingSpaces.length); }); - it('non string', function () + it('non string', () => { - const arr = TextMetrics.tokenize({}); + // @ts-expect-error - should return false on non-string input + const arr = TextMetrics['tokenize']({}); - expect(arr).to.be.an('array'); - expect(arr.length).to.equal(0); + expect(arr).toBeArray(); + expect(arr.length).toEqual(0); }); }); - describe('collapseSpaces', function () + describe('collapseSpaces', () => { - it('pre', function () + it('pre', () => { - const bool = TextMetrics.collapseSpaces('pre'); + const bool = TextMetrics['collapseSpaces']('pre'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('normal', function () + it('normal', () => { - const bool = TextMetrics.collapseSpaces('normal'); + const bool = TextMetrics['collapseSpaces']('normal'); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('pre-line', function () + it('pre-line', () => { - const bool = TextMetrics.collapseSpaces('pre-line'); + const bool = TextMetrics['collapseSpaces']('pre-line'); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('non matching string', function () + it('non matching string', () => { - const bool = TextMetrics.collapseSpaces('bull'); + // @ts-expect-error - should return false on non matching string + const bool = TextMetrics['collapseSpaces']('bull'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('non string', function () + it('non string', () => { - const bool = TextMetrics.collapseSpaces({}); + // @ts-expect-error - should return false on non-string input + const bool = TextMetrics['collapseSpaces']({}); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); }); - describe('collapseNewlines', function () + describe('collapseNewlines', () => { - it('pre', function () + it('pre', () => { - const bool = TextMetrics.collapseNewlines('pre'); + const bool = TextMetrics['collapseNewlines']('pre'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('normal', function () + it('normal', () => { - const bool = TextMetrics.collapseNewlines('normal'); + const bool = TextMetrics['collapseNewlines']('normal'); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('pre-line', function () + it('pre-line', () => { - const bool = TextMetrics.collapseNewlines('pre-line'); + const bool = TextMetrics['collapseNewlines']('pre-line'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('non matching string', function () + it('non matching string', () => { - const bool = TextMetrics.collapseNewlines('bull'); + // @ts-expect-error - should return false on non matching string + const bool = TextMetrics['collapseNewlines']('bull'); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); - it('non string', function () + it('non string', () => { - const bool = TextMetrics.collapseNewlines({}); + // @ts-expect-error - should return false on non-string input + const bool = TextMetrics['collapseNewlines']({}); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); }); - describe('canBreakWords', function () + describe('canBreakWords', () => { - it('breakWords: true', function () + it('breakWords: true', () => { const bool = TextMetrics.canBreakWords('text', true); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('breakWords: false', function () + it('breakWords: false', () => { const bool = TextMetrics.canBreakWords('text', false); - expect(bool).to.equal(false); + expect(bool).toEqual(false); }); }); - describe('canBreakChars', function () + describe('canBreakChars', () => { - it('should always return true', function () + it('should always return true', () => { - const bool = TextMetrics.canBreakChars(); + // @ts-expect-error - function is meant to be overridden + const bool = TextMetrics['canBreakChars'](); - expect(bool).to.equal(true); + expect(bool).toEqual(true); }); - it('should prevent breaking for all numbers', function () + it('should prevent breaking for all numbers', () => { const style = new TextStyle({ fontFamily: 'Arial', fontSize: 26, fontStyle: 'italic', fontVariant: 'normal', - fontWeight: 900, + fontWeight: '900', wordWrap: true, wordWrapWidth: 300, letterSpacing: 4, @@ -693,21 +710,17 @@ describe('TextMetrics', function () const str = '-------0000,1111,9999------'; const reg = /^\d+$/; - TextMetrics.canBreakWords = function () - { - return true; - }; + TextMetrics.canBreakWords = () => + true; // override breakChars - TextMetrics.canBreakChars = function (char, nextChar) - { - return !(char.match(reg) && nextChar.match(reg)); - }; + TextMetrics.canBreakChars = (char, nextChar) => + !(char.match(reg) && nextChar.match(reg)); const metrics = TextMetrics.measureText(str, style); - expect(metrics.lines[0]).to.equal('-------0000,1111,'); - expect(metrics.lines[1]).to.equal('9999------'); + expect(metrics.lines[0]).toEqual('-------0000,1111,'); + expect(metrics.lines[1]).toEqual('9999------'); }); }); }); diff --git a/packages/text/test/TextStyle.tests.ts b/packages/text/test/TextStyle.tests.ts index 975c0fc8a95..a0f531ccea5 100644 --- a/packages/text/test/TextStyle.tests.ts +++ b/packages/text/test/TextStyle.tests.ts @@ -1,68 +1,67 @@ import { TextStyle } from '@pixi/text'; -import { expect } from 'chai'; -describe('TextStyle', function () +describe('TextStyle', () => { - it('reset reverts style to default', function () + it('reset reverts style to default', () => { const textStyle = new TextStyle(); const defaultFontSize = textStyle.fontSize; textStyle.fontSize = 1000; - expect(textStyle.fontSize).to.equal(1000); + expect(textStyle.fontSize).toEqual(1000); textStyle.reset(); - expect(textStyle.fontSize).to.equal(defaultFontSize); + expect(textStyle.fontSize).toEqual(defaultFontSize); }); - it('should clone correctly', function () + it('should clone correctly', () => { const textStyle = new TextStyle({ fontSize: 1000 }); const clonedTextStyle = textStyle.clone(); - expect(textStyle.fontSize).to.equal(1000); - expect(clonedTextStyle.fontSize).to.equal(textStyle.fontSize); + expect(textStyle.fontSize).toEqual(1000); + expect(clonedTextStyle.fontSize).toEqual(textStyle.fontSize); }); - it('should assume pixel fonts', function () + it('should assume pixel fonts', () => { const style = new TextStyle({ fontSize: 72 }); const font = style.toFontString(); - expect(font).to.be.a.string; - expect(font).to.have.string(' 72px '); + expect(font).toBeString(); + expect(font).toContain(' 72px '); }); - it('should handle multiple fonts as array', function () + it('should handle multiple fonts as array', () => { const style = new TextStyle({ fontFamily: ['Georgia', 'Arial', 'sans-serif'], }); - expect(style.toFontString()).to.have.string('"Georgia","Arial",sans-serif'); + expect(style.toFontString()).toContain('"Georgia","Arial",sans-serif'); }); - it('should handle multiple fonts as string', function () + it('should handle multiple fonts as string', () => { const style = new TextStyle({ fontFamily: 'Georgia, "Arial", sans-serif', }); - expect(style.toFontString()).to.have.string('"Georgia","Arial",sans-serif'); + expect(style.toFontString()).toContain('"Georgia","Arial",sans-serif'); }); - it('should not shared array / object references between different instances', function () + it('should not shared array / object references between different instances', () => { const defaultStyle = new TextStyle(); const style = new TextStyle(); - expect(defaultStyle.fillGradientStops.length).to.equal(style.fillGradientStops.length); + expect(defaultStyle.fillGradientStops.length).toEqual(style.fillGradientStops.length); style.fillGradientStops.push(0); - expect(defaultStyle.fillGradientStops.length).to.not.equal(style.fillGradientStops.length); + expect(defaultStyle.fillGradientStops.length).not.toEqual(style.fillGradientStops.length); }); - it('should not quote generic font families when calling toFontString', function () + it('should not quote generic font families when calling toFontString', () => { // Should match the list in TextStyle const genericFontFamilies = [ @@ -87,7 +86,7 @@ describe('TextStyle', function () const regex = new RegExp(incorrectRegexTemplate.replace('FAMILY', genericFamily)); const result = style.toFontString().match(regex); - expect(result).to.be.null; + expect(result).toBeNull(); } }); }); diff --git a/packages/ticker/README.md b/packages/ticker/README.md index 6c0f8e52cf8..00ba18779e6 100644 --- a/packages/ticker/README.md +++ b/packages/ticker/README.md @@ -20,11 +20,9 @@ ticker.start(); Use as an Application plugin: ```js -import { TickerPlugin } from '@pixi/ticker'; +import '@pixi/ticker'; import { Application } from '@pixi/app'; -Application.registerPlugin(TickerPlugin); - const app = new Application(); app.ticker.start(); ``` \ No newline at end of file diff --git a/packages/ticker/package.json b/packages/ticker/package.json index e901314f6cd..f94649350f1 100644 --- a/packages/ticker/package.json +++ b/packages/ticker/package.json @@ -1,9 +1,21 @@ { "name": "@pixi/ticker", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/ticker.js", - "module": "dist/esm/ticker.js", - "bundle": "dist/browser/ticker.js", + "module": "dist/esm/ticker.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/ticker.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/ticker.js" + } + } + }, "description": "Tickers are control the timings within PixiJS", "author": "Mat Groves", "contributors": [ @@ -20,11 +32,11 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], - "peerDependencies": { - "@pixi/settings": "6.3.0" + "dependencies": { + "@pixi/extensions": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha" } } diff --git a/packages/ticker/src/Ticker.ts b/packages/ticker/src/Ticker.ts index 56ec93b7a8b..c05ac3305a7 100644 --- a/packages/ticker/src/Ticker.ts +++ b/packages/ticker/src/Ticker.ts @@ -9,7 +9,6 @@ export type TickerCallback = (this: T, dt: number) => any; * * This class is composed around listeners meant for execution on the next requested animation frame. * Animation frames are requested only when necessary, e.g. When the ticker is started and the emitter has listeners. - * * @class * @memberof PIXI */ @@ -96,10 +95,7 @@ export class Ticker private _minElapsedMS = 0; /** If enabled, deleting is disabled.*/ private _protected = false; - /** - * The last time keyframe was executed. - * Maintains a relatively fixed interval with the previous value. - */ + /** The last time keyframe was executed. Maintains a relatively fixed interval with the previous value. */ private _lastFrame = -1; /** * Internal tick method bound to ticker instance. @@ -108,7 +104,6 @@ export class Ticker * Also separating frame requests from update method * so listeners may be called at any time and with * any animation API, just invoke ticker.update(time). - * * @param time - Time since last tick. */ private _tick: (time: number) => any; @@ -140,7 +135,6 @@ export class Ticker * Conditionally requests a new animation frame. * If a frame has not already been requested, and if the internal * emitter has listeners, a new frame is requested. - * * @private */ private _requestIfNeeded(): void @@ -174,7 +168,6 @@ export class Ticker * conditions are met, a new frame is requested. If the ticker has not * been started, but autoStart is `true`, then the ticker starts now, * and continues with the previous conditions to request a new frame. - * * @private */ private _startIfPossible(): void @@ -192,7 +185,6 @@ export class Ticker /** * Register a handler for tick events. Calls continuously unless * it is removed or the ticker is stopped. - * * @param fn - The listener function to be added for updates * @param context - The listener context * @param {number} [priority=PIXI.UPDATE_PRIORITY.NORMAL] - The priority for emitting @@ -205,7 +197,6 @@ export class Ticker /** * Add a handler for the tick event which is only execute once. - * * @param fn - The listener function to be added for one update * @param context - The listener context * @param {number} [priority=PIXI.UPDATE_PRIORITY.NORMAL] - The priority for emitting @@ -220,7 +211,6 @@ export class Ticker * Internally adds the event handler so that it can be sorted by priority. * Priority allows certain handler (user, AnimatedSprite, Interaction) to be run * before the rendering. - * * @private * @param listener - Current listener being added. * @returns This instance of a ticker @@ -265,7 +255,6 @@ export class Ticker /** * Removes any handlers matching the function and context parameters. * If no handlers are left after removing, then it cancels the animation frame. - * * @param fn - The listener function to be removed * @param context - The listener context to be removed * @returns This instance of a ticker @@ -299,7 +288,6 @@ export class Ticker /** * The number of listeners on this ticker, calculated by walking through linked list - * * @readonly * @member {number} */ @@ -321,10 +309,7 @@ export class Ticker return count; } - /** - * Starts the ticker. If the ticker has listeners - * a new animation frame is requested at this point. - */ + /** Starts the ticker. If the ticker has listeners a new animation frame is requested at this point. */ start(): void { if (!this.started) @@ -334,10 +319,7 @@ export class Ticker } } - /** - * Stops the ticker. If the ticker has requested - * an animation frame it is canceled at this point. - */ + /** Stops the ticker. If the ticker has requested an animation frame it is canceled at this point. */ stop(): void { if (this.started) @@ -347,10 +329,7 @@ export class Ticker } } - /** - * Destroy the ticker and don't use after this. Calling - * this method removes all references to internal events. - */ + /** Destroy the ticker and don't use after this. Calling this method removes all references to internal events. */ destroy(): void { if (!this._protected) @@ -379,7 +358,6 @@ export class Ticker * This method will be called automatically by animation * frame callbacks if the ticker instance has been started * and listeners are added. - * * @param {number} [currentTime=performance.now()] - the current time of execution */ update(currentTime = performance.now()): void @@ -463,7 +441,6 @@ export class Ticker * **Note:** This does not factor in the value of * {@link PIXI.Ticker#speed}, which is specific * to scaling {@link PIXI.Ticker#deltaTime}. - * * @member {number} * @readonly */ @@ -479,7 +456,6 @@ export class Ticker * but does not effect the measured value of {@link PIXI.Ticker#FPS}. * When setting this property it is clamped to a value between * `0` and `PIXI.settings.TARGET_FPMS * 1000`. - * * @member {number} * @default 10 */ @@ -505,7 +481,6 @@ export class Ticker * This will effect the measured value of {@link PIXI.Ticker#FPS}. * If it is set to `0`, then there is no limit; PixiJS will render as many frames as it can. * Otherwise it will be at least `minFPS` - * * @member {number} * @default 0 */ @@ -542,7 +517,6 @@ export class Ticker * * The property {@link PIXI.Ticker#autoStart} is set to `true` for this instance. * Please follow the examples for usage, including how to opt-out of auto-starting the shared ticker. - * * @example * let ticker = PIXI.Ticker.shared; * // Set this to prevent starting this ticker when listeners are added. @@ -553,7 +527,6 @@ export class Ticker * ticker.stop(); * // Call this when you are ready for a running shared ticker. * ticker.start(); - * * @example * // You may use the shared ticker to render... * let renderer = PIXI.autoDetectRenderer(); @@ -562,7 +535,6 @@ export class Ticker * ticker.add(function (time) { * renderer.render(stage); * }); - * * @example * // Or you can just update it manually. * ticker.autoStart = false; @@ -573,7 +545,6 @@ export class Ticker * requestAnimationFrame(animate); * } * animate(performance.now()); - * * @member {PIXI.Ticker} * @static */ @@ -591,12 +562,11 @@ export class Ticker } /** - * The system ticker instance used by {@link PIXI.InteractionManager} and by - * {@link PIXI.BasePrepare} for core timing functionality that shouldn't usually need to be paused, - * unlike the `shared` ticker which drives visual animations and rendering which may want to be paused. + * The system ticker instance used by {@link PIXI.BasePrepare} for core timing + * functionality that shouldn't usually need to be paused, unlike the `shared` + * ticker which drives visual animations and rendering which may want to be paused. * * The property {@link PIXI.Ticker#autoStart} is set to `true` for this instance. - * * @member {PIXI.Ticker} * @static */ diff --git a/packages/ticker/src/TickerListener.ts b/packages/ticker/src/TickerListener.ts index ec6f0f991be..40191b9bfc8 100644 --- a/packages/ticker/src/TickerListener.ts +++ b/packages/ticker/src/TickerListener.ts @@ -1,8 +1,7 @@ -import { TickerCallback } from './Ticker'; +import type { TickerCallback } from './Ticker'; /** * Internal class for handling the priority sorting of ticker handlers. - * * @private * @class * @memberof PIXI @@ -46,7 +45,7 @@ export class TickerListener * @private * @param fn - The listener function to be added for one update * @param context - The listener context - * @return `true` if the listener match the arguments + * @returns `true` if the listener match the arguments */ match(fn: TickerCallback, context: any = null): boolean { @@ -57,7 +56,7 @@ export class TickerListener * Emit by calling the current function. * @private * @param deltaTime - time since the last emit. - * @return Next ticker + * @returns Next ticker */ emit(deltaTime: number): TickerListener { @@ -111,7 +110,7 @@ export class TickerListener * @private * @param hard - `true` to remove the `next` reference, this * is considered a hard destroy. Soft destroy maintains the next reference. - * @return The listener to redirect while emitting or removing. + * @returns The listener to redirect while emitting or removing. */ destroy(hard = false): TickerListener { diff --git a/packages/ticker/src/TickerPlugin.ts b/packages/ticker/src/TickerPlugin.ts index bdf0a48f158..407765d95f1 100644 --- a/packages/ticker/src/TickerPlugin.ts +++ b/packages/ticker/src/TickerPlugin.ts @@ -1,19 +1,18 @@ +import type { ExtensionMetadata } from '@pixi/extensions'; +import { extensions, ExtensionType } from '@pixi/extensions'; import { UPDATE_PRIORITY } from './const'; import { Ticker } from './Ticker'; /** * Middleware for for Application Ticker. - * - * @example - * import {TickerPlugin} from '@pixi/ticker'; - * import {Application} from '@pixi/app'; - * Application.registerPlugin(TickerPlugin); - * * @class * @memberof PIXI */ export class TickerPlugin { + /** @ignore */ + static extension: ExtensionMetadata = ExtensionType.Application; + static start: () => void; static stop: () => void; static _ticker: Ticker; @@ -21,7 +20,6 @@ export class TickerPlugin /** * Initialize the plugin with scope of application instance - * * @static * @private * @param {object} [options] - See application options @@ -57,7 +55,6 @@ export class TickerPlugin /** * Convenience method for stopping the render. - * * @method * @memberof PIXI.Application * @instance @@ -69,7 +66,6 @@ export class TickerPlugin /** * Convenience method for starting the render. - * * @method * @memberof PIXI.Application * @instance @@ -81,7 +77,6 @@ export class TickerPlugin /** * Internal reference to the ticker. - * * @type {PIXI.Ticker} * @name _ticker * @memberof PIXI.Application# @@ -91,7 +86,6 @@ export class TickerPlugin /** * Ticker for doing render updates. - * * @type {PIXI.Ticker} * @name ticker * @memberof PIXI.Application# @@ -108,7 +102,6 @@ export class TickerPlugin /** * Clean up the ticker, scoped to application. - * * @static * @private */ @@ -123,3 +116,5 @@ export class TickerPlugin } } } + +extensions.add(TickerPlugin); diff --git a/packages/ticker/src/const.ts b/packages/ticker/src/const.ts index be6b47c1e1e..4ac3c3c0b5e 100644 --- a/packages/ticker/src/const.ts +++ b/packages/ticker/src/const.ts @@ -2,20 +2,19 @@ * Represents the update priorities used by internal PIXI classes when registered with * the {@link PIXI.Ticker} object. Higher priority items are updated first and lower * priority items, such as render, should go later. - * * @static * @constant * @name UPDATE_PRIORITY * @memberof PIXI * @enum {number} - * @property {number} INTERACTION=50 Highest priority, used for {@link PIXI.InteractionManager} - * @property {number} HIGH=25 High priority updating, {@link PIXI.VideoBaseTexture} and {@link PIXI.AnimatedSprite} - * @property {number} NORMAL=0 Default priority for ticker events, see {@link PIXI.Ticker#add}. - * @property {number} LOW=-25 Low priority used for {@link PIXI.Application} rendering. - * @property {number} UTILITY=-50 Lowest priority used for {@link PIXI.BasePrepare} utility. + * @property {number} [HIGH=25] High priority updating, {@link PIXI.VideoBaseTexture} and {@link PIXI.AnimatedSprite} + * @property {number} [NORMAL=0] Default priority for ticker events, see {@link PIXI.Ticker#add}. + * @property {number} [LOW=-25] Low priority used for {@link PIXI.Application} rendering. + * @property {number} [UTILITY=-50] Lowest priority used for {@link PIXI.BasePrepare} utility. */ -export enum UPDATE_PRIORITY { - INTERACTION = 50, +export enum UPDATE_PRIORITY +// eslint-disable-next-line @typescript-eslint/indent +{ HIGH = 25, NORMAL = 0, LOW = -25, diff --git a/packages/ticker/src/settings.ts b/packages/ticker/src/settings.ts index 9a935a71266..0717bf2335a 100644 --- a/packages/ticker/src/settings.ts +++ b/packages/ticker/src/settings.ts @@ -2,7 +2,6 @@ import { settings } from '@pixi/settings'; /** * Target frames per millisecond. - * * @static * @name TARGET_FPMS * @memberof PIXI.settings diff --git a/packages/ticker/test/Ticker.tests.ts b/packages/ticker/test/Ticker.tests.ts index 01ee5dea801..ea21b036817 100644 --- a/packages/ticker/test/Ticker.tests.ts +++ b/packages/ticker/test/Ticker.tests.ts @@ -1,23 +1,23 @@ import { Ticker, UPDATE_PRIORITY } from '@pixi/ticker'; -import sinon from 'sinon'; -import { expect } from 'chai'; const { shared, system } = Ticker; -describe('Ticker', function () +describe('Ticker', () => { - before(function () + let length: (ticker?: Ticker) => number; + + beforeAll(() => { - this.length = (ticker) => + length = (ticker?: Ticker) => { ticker = ticker || shared; - if (!ticker._head || !ticker._head.next) + if (!ticker['_head'] || !ticker['_head'].next) { return 0; } - let listener = ticker._head.next; + let listener = ticker['_head'].next; let i = 0; while (listener) @@ -30,174 +30,176 @@ describe('Ticker', function () }; }); - it('should be available', function () + it('should be available', () => { - expect(Ticker).to.be.a('function'); - expect(shared).to.be.an.instanceof(Ticker); - expect(system).to.be.an.instanceof(Ticker); + expect(Ticker).toBeInstanceOf(Function); + expect(shared).toBeInstanceOf(Ticker); + expect(system).toBeInstanceOf(Ticker); }); - it('should create a new ticker and destroy it', function () + it('should create a new ticker and destroy it', () => { const ticker = new Ticker(); ticker.start(); - const listener = sinon.spy(); + const listener = jest.fn(); - expect(this.length(ticker)).to.equal(0); + expect(length(ticker)).toEqual(0); ticker.add(listener); - expect(this.length(ticker)).to.equal(1); + expect(length(ticker)).toEqual(1); ticker.destroy(); - expect(ticker._head).to.be.null; - expect(ticker.started).to.be.false; - expect(this.length(ticker)).to.equal(0); + expect(ticker['_head']).toBeNull(); + expect(ticker.started).toBe(false); + expect(length(ticker)).toEqual(0); }); - it('should protect destroying shared ticker', function () + it('should protect destroying shared ticker', () => { - const listener = sinon.spy(); + const listener = jest.fn(); shared.add(listener); // needed to autoStart shared.destroy(); - expect(shared._head).to.not.be.null; - expect(shared.started).to.be.true; + expect(shared['_head']).not.toBeNull(); + expect(shared.started).toBe(true); }); - it('should protect destroying system ticker', function () + it('should protect destroying system ticker', () => { - const listener = sinon.spy(); + const listener = jest.fn(); system.add(listener); // needed to autoStart system.destroy(); - expect(system._head).to.not.be.null; - expect(system.started).to.be.true; + expect(system['_head']).not.toBeNull(); + expect(system.started).toBe(true); }); - it('should add and remove listener', function () + it('should add and remove listener', () => { - const listener = sinon.spy(); - const length = this.length(); + const listener = jest.fn(); + const len = length(); shared.add(listener); - expect(this.length()).to.equal(length + 1); + expect(length()).toEqual(len + 1); shared.remove(listener); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should update a listener', function () + it('should update a listener', () => { - const listener = sinon.spy(); + const listener = jest.fn(); shared.add(listener); shared.update(); - expect(listener.calledOnce).to.be.true; + expect(listener).toBeCalledTimes(1); shared.remove(listener); shared.update(); - expect(listener.calledOnce).to.be.true; + expect(listener).toBeCalledTimes(1); }); - it('should update a listener twice and remove once', function () + it('should update a listener twice and remove once', () => { - const listener = sinon.spy(); - const length = this.length(); + const listener = jest.fn(); + const len = length(); shared.add(listener).add(listener); shared.update(); - expect(listener.calledTwice).to.be.true; - expect(this.length()).to.equal(length + 2); + expect(listener).toBeCalledTimes(2); + expect(length()).toEqual(len + 2); shared.remove(listener); shared.update(); - expect(listener.calledTwice).to.be.true; - expect(this.length()).to.equal(length); + expect(listener).toBeCalledTimes(2); + expect(length()).toEqual(len); }); - it('should count listeners correctly', function () + it('should count listeners correctly', () => { const ticker = new Ticker(); - expect(ticker.count).to.equal(0); + expect(ticker.count).toEqual(0); - const listener = sinon.spy(); + const listener = jest.fn(); ticker.add(listener); - expect(ticker.count).to.equal(1); + expect(ticker.count).toEqual(1); ticker.add(listener); - expect(ticker.count).to.equal(2); + expect(ticker.count).toEqual(2); ticker.remove(listener); - expect(ticker.count).to.equal(0); + expect(ticker.count).toEqual(0); ticker.destroy(); - expect(ticker._head).to.be.null; - expect(ticker.started).to.be.false; - expect(this.length(ticker)).to.equal(0); + expect(ticker['_head']).toBeNull(); + expect(ticker.started).toBe(false); + expect(length(ticker)).toEqual(0); }); - it('should respect priority order', function () + it('should respect priority order', () => { - const length = this.length(); - const listener1 = sinon.spy(); - const listener2 = sinon.spy(); - const listener3 = sinon.spy(); - const listener4 = sinon.spy(); + const len = length(); + const listener1 = jest.fn(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); shared.add(listener1, null, UPDATE_PRIORITY.LOW) - .add(listener4, null, UPDATE_PRIORITY.INTERACTION) .add(listener3, null, UPDATE_PRIORITY.HIGH) .add(listener2, null, UPDATE_PRIORITY.NORMAL); shared.update(); - expect(this.length()).to.equal(length + 4); + expect(length()).toEqual(len + 3); + + const l3 = listener3.mock.invocationCallOrder[0]; + const l2 = listener2.mock.invocationCallOrder[0]; + const l1 = listener1.mock.invocationCallOrder[0]; - sinon.assert.callOrder(listener4, listener3, listener2, listener1); + expect(l3).toBeLessThan(l2); + expect(l2).toBeLessThan(l1); shared.remove(listener1) .remove(listener2) - .remove(listener3) - .remove(listener4); + .remove(listener3); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should auto-remove once listeners', function () + it('should auto-remove once listeners', () => { - const length = this.length(); - const listener = sinon.spy(); + const len = length(); + const listener = jest.fn(); shared.addOnce(listener); shared.update(); - expect(listener.calledOnce).to.be.true; - expect(this.length()).to.equal(length); + expect(listener).toBeCalledTimes(1); + expect(length()).toEqual(len); }); - it('should call when adding same priority', function () + it('should call when adding same priority', () => { - const length = this.length(); - const listener1 = sinon.spy(); - const listener2 = sinon.spy(); - const listener3 = sinon.spy(); + const len = length(); + const listener1 = jest.fn(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); shared.add(listener1) .add(listener2) @@ -205,23 +207,28 @@ describe('Ticker', function () shared.update(); - expect(this.length()).to.equal(length + 3); + expect(length()).toEqual(len + 3); + + const l3 = listener3.mock.invocationCallOrder[0]; + const l2 = listener2.mock.invocationCallOrder[0]; + const l1 = listener1.mock.invocationCallOrder[0]; - sinon.assert.callOrder(listener1, listener2, listener3); + expect(l1).toBeLessThan(l2); + expect(l2).toBeLessThan(l3); shared.remove(listener1) .remove(listener2) .remove(listener3); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it.skip('should remove once listener in a stack', function () + it('should remove once listener in a stack', () => { - const length = this.length(); - const listener1 = sinon.spy(); - const listener2 = sinon.spy(); - const listener3 = sinon.spy(); + const len = length(); + const listener1 = jest.fn(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); shared.add(listener1, null, UPDATE_PRIORITY.HIGH); shared.addOnce(listener2, null, UPDATE_PRIORITY.NORMAL); @@ -229,25 +236,25 @@ describe('Ticker', function () shared.update(); - expect(this.length()).to.equal(length + 2); + expect(length()).toEqual(len + 2); shared.update(); - expect(listener1.calledTwice).to.be.true; - expect(listener2.calledOnce).to.be.true; - expect(listener3.calledTwice).to.be.true; + expect(listener1).toBeCalledTimes(2); + expect(listener2).toBeCalledTimes(1); + expect(listener3).toBeCalledTimes(2); shared.remove(listener1).remove(listener3); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should call inserted item with a lower priority', function () + it('should call inserted item with a lower priority', () => { - const length = this.length(); - const lowListener = sinon.spy(); - const highListener = sinon.spy(); - const mainListener = sinon.spy(() => + const len = length(); + const lowListener = jest.fn(); + const highListener = jest.fn(); + const mainListener = jest.fn(() => { shared.add(highListener, null, UPDATE_PRIORITY.HIGH); shared.add(lowListener, null, UPDATE_PRIORITY.LOW); @@ -257,24 +264,24 @@ describe('Ticker', function () shared.update(); - expect(this.length()).to.equal(length + 3); + expect(length()).toEqual(len + 3); - expect(mainListener.calledOnce).to.be.true; - expect(lowListener.calledOnce).to.be.true; - expect(highListener.calledOnce).to.be.false; + expect(mainListener).toBeCalledTimes(1); + expect(lowListener).toBeCalledTimes(1); + expect(highListener).not.toBeCalled(); shared.remove(mainListener) .remove(highListener) .remove(lowListener); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should remove emit low-priority item during emit', function () + it('should remove emit low-priority item during emit', () => { - const length = this.length(); - const listener2 = sinon.spy(); - const listener1 = sinon.spy(() => + const len = length(); + const listener2 = jest.fn(); + const listener1 = jest.fn(() => { shared.add(listener2, null, UPDATE_PRIORITY.LOW); }); @@ -283,131 +290,131 @@ describe('Ticker', function () shared.update(); - expect(this.length()).to.equal(length + 2); + expect(length()).toEqual(len + 2); - expect(listener2.calledOnce).to.be.true; - expect(listener1.calledOnce).to.be.true; + expect(listener2).toBeCalledTimes(1); + expect(listener1).toBeCalledTimes(1); shared.remove(listener1) .remove(listener2); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should remove itself on emit after adding new item', function () + it('should remove itself on emit after adding new item', () => { - const length = this.length(); - const listener2 = sinon.spy(); - const listener1 = sinon.spy(() => + const len = length(); + const listener2 = jest.fn(); + const listener1 = jest.fn(() => { shared.add(listener2, null, UPDATE_PRIORITY.LOW); shared.remove(listener1); // listener is removed right away - expect(this.length()).to.equal(length + 1); + expect(length()).toEqual(len + 1); }); shared.add(listener1, null, UPDATE_PRIORITY.NORMAL); shared.update(); - expect(this.length()).to.equal(length + 1); + expect(length()).toEqual(len + 1); - expect(listener2.calledOnce).to.be.true; - expect(listener1.calledOnce).to.be.true; + expect(listener2).toBeCalledTimes(1); + expect(listener1).toBeCalledTimes(1); shared.remove(listener2); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it.skip('should remove itself before, still calling new item', function () + it('should remove itself before, still calling new item', () => { - const length = this.length(); - const listener2 = sinon.spy(); - const listener1 = sinon.spy(() => + const len = length(); + const listener2 = jest.fn(); + const listener1 = jest.fn(() => { shared.remove(listener1); shared.add(listener2, null, UPDATE_PRIORITY.LOW); // listener is removed right away - expect(this.length()).to.equal(length + 1); + expect(length()).toEqual(len + 1); }); shared.add(listener1, null, UPDATE_PRIORITY.NORMAL); shared.update(); - expect(this.length()).to.equal(length + 1); + expect(length()).toEqual(len + 1); - expect(listener2.called).to.be.false; - expect(listener1.calledOnce).to.be.true; + expect(listener2).not.toHaveBeenCalled(); + expect(listener1).toBeCalledTimes(1); shared.update(); - expect(listener2.calledOnce).to.be.true; - expect(listener1.calledOnce).to.be.true; + expect(listener2).toBeCalledTimes(1); + expect(listener1).toBeCalledTimes(1); shared.remove(listener2); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it.skip('should remove items before and after current priority', function () + it('should remove items before and after current priority', () => { - const length = this.length(); - const listener2 = sinon.spy(); - const listener3 = sinon.spy(); - const listener4 = sinon.spy(); + const len = length(); + const listener2 = jest.fn(); + const listener3 = jest.fn(); + const listener4 = jest.fn(); shared.add(listener2, null, UPDATE_PRIORITY.HIGH); shared.add(listener3, null, UPDATE_PRIORITY.LOW); shared.add(listener4, null, UPDATE_PRIORITY.LOW); - const listener1 = sinon.spy(() => + const listener1 = jest.fn(() => { shared.remove(listener2) .remove(listener3); // listener is removed right away - expect(this.length()).to.equal(length + 2); + expect(length()).toEqual(len + 2); }); shared.add(listener1, null, UPDATE_PRIORITY.NORMAL); shared.update(); - expect(this.length()).to.equal(length + 2); + expect(length()).toEqual(len + 2); - expect(listener2.calledOnce).to.be.true; - expect(listener3.calledOnce).to.be.false; - expect(listener4.calledOnce).to.be.true; - expect(listener1.calledOnce).to.be.true; + expect(listener2).toBeCalledTimes(1); + expect(listener3).not.toBeCalled(); + expect(listener4).toBeCalledTimes(1); + expect(listener1).toBeCalledTimes(1); shared.update(); - expect(listener2.calledOnce).to.be.true; - expect(listener3.calledOnce).to.be.false; - expect(listener4.calledTwice).to.be.true; - expect(listener1.calledTwice).to.be.true; + expect(listener2).toBeCalledTimes(1); + expect(listener3).not.toBeCalled(); + expect(listener4).toBeCalledTimes(2); + expect(listener1).toBeCalledTimes(2); shared.remove(listener1) .remove(listener4); - expect(this.length()).to.equal(length); + expect(length()).toEqual(len); }); - it('should destroy on listener', function (done) + it('should destroy on listener', (done) => { const ticker = new Ticker(); - const listener2 = sinon.spy(); - const listener = sinon.spy(() => + const listener2 = jest.fn(); + const listener = jest.fn(() => { ticker.destroy(); setTimeout(() => { - expect(listener2.called).to.be.false; - expect(listener.calledOnce).to.be.true; + expect(listener2).not.toHaveBeenCalled(); + expect(listener).toBeCalledTimes(1); done(); }, 0); }); @@ -417,23 +424,23 @@ describe('Ticker', function () ticker.start(); }); - it('should Ticker call destroyed listener "next" pointer after destroy', function (done) + it('should Ticker call destroyed listener "next" pointer after destroy', (done) => { const ticker = new Ticker(); - const listener1 = sinon.spy(); - const listener2 = sinon.spy(() => + const listener1 = jest.fn(); + const listener2 = jest.fn(() => { ticker.remove(listener2); }); - const listener3 = sinon.spy(() => + const listener3 = jest.fn(() => { ticker.stop(); - expect(listener1.calledOnce).to.be.true; - expect(listener2.calledOnce).to.be.true; - expect(listener3.calledOnce).to.be.true; + expect(listener1).toBeCalledTimes(1); + expect(listener2).toBeCalledTimes(1); + expect(listener3).toBeCalledTimes(1); done(); }); diff --git a/packages/ticker/test/TickerPlugin.tests.ts b/packages/ticker/test/TickerPlugin.tests.ts index 47b6f47297b..2c4abbed63b 100644 --- a/packages/ticker/test/TickerPlugin.tests.ts +++ b/packages/ticker/test/TickerPlugin.tests.ts @@ -1,92 +1,93 @@ -import { TickerPlugin, UPDATE_PRIORITY, Ticker } from '@pixi/ticker'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { Ticker, TickerPlugin, UPDATE_PRIORITY } from '@pixi/ticker'; -describe('TickerPlugin', function () +describe('TickerPlugin', () => { - it('should not start application before calling start method if options.autoStart is false', function (done) + interface App { - const app = {}; + _ticker?: Ticker; + ticker?: Ticker; + render?(): void; + start?(): void; + } + let app: App; + + it('should not start application before calling start method if options.autoStart is false', (done) => + { + const appp = {} as App; - TickerPlugin.init.call(app, { autoStart: false }); + TickerPlugin.init.call(appp, { autoStart: false }); - expect(app.ticker).to.be.instanceof(Ticker); - expect(app.ticker.started).to.be.false; + expect(appp.ticker).toBeInstanceOf(Ticker); + expect(appp.ticker.started).toBe(false); - app.start(); + appp.start(); - app.ticker.addOnce(() => + appp.ticker.addOnce(() => { - TickerPlugin.destroy.call(app); + TickerPlugin.destroy.call(appp); done(); }); }); - describe('set ticker', function () + describe('set ticker', () => { - before(function () + beforeAll(() => { - this.app = { + app = { render() { // do nothing }, }; - TickerPlugin.init.call(this.app); + TickerPlugin.init.call(app); /* remove default listener to prevent uncaught exception */ - this.app._ticker.remove(this.app.render, this.app); + app._ticker.remove(app.render, app); }); - after(function () + afterAll(() => { - TickerPlugin.destroy.call(this.app); + TickerPlugin.destroy.call(app); }); - it('should assign ticker object', function () + it('should assign ticker object', () => { - const ticker = { add: sinon.spy() }; - const _ticker = { remove: sinon.spy() }; + const ticker = { add: jest.fn() }; + const _ticker = { remove: jest.fn() }; - this.app._ticker = _ticker; - this.app.ticker = ticker; + app._ticker = _ticker as unknown as Ticker; + app.ticker = ticker as unknown as Ticker; - expect(_ticker.remove).to.be.calledOnce; - expect(_ticker.remove.args[0][0]).to.be.equal(this.app.render); - expect(_ticker.remove.args[0][1]).to.be.equal(this.app); + expect(_ticker.remove).toHaveBeenCalledOnce(); + expect(_ticker.remove).toBeCalledWith(app.render, app); - expect(this.app._ticker).to.be.equal(ticker); - expect(ticker.add).to.be.calledOnce; - expect(ticker.add.args[0][0]).to.be.equal(this.app.render); - expect(ticker.add.args[0][1]).to.be.equal(this.app); - expect(ticker.add.args[0][2]).to.be.equal(UPDATE_PRIORITY.LOW); + expect(app._ticker).toEqual(ticker); + expect(ticker.add).toHaveBeenCalledOnce(); + expect(ticker.add).toBeCalledWith(app.render, app, UPDATE_PRIORITY.LOW); }); - it('should assign ticker if no ticker', function () + it('should assign ticker if no ticker', () => { - const ticker = { add: sinon.spy() }; + const ticker = { add: jest.fn() }; - this.app._ticker = null; - this.app.ticker = ticker; + app._ticker = null; + app.ticker = ticker as unknown as Ticker; - expect(this.app._ticker).to.be.equal(ticker); - expect(ticker.add).to.be.calledOnce; - expect(ticker.add.args[0][0]).to.be.equal(this.app.render); - expect(ticker.add.args[0][1]).to.be.equal(this.app); - expect(ticker.add.args[0][2]).to.be.equal(UPDATE_PRIORITY.LOW); + expect(app._ticker).toEqual(ticker); + expect(ticker.add).toHaveBeenCalledOnce(); + expect(ticker.add).toBeCalledWith(app.render, app, UPDATE_PRIORITY.LOW); }); - it('should assign null ticker', function () + it('should assign null ticker', () => { - const _ticker = { remove: sinon.spy() }; + const _ticker = { remove: jest.fn() }; - this.app._ticker = _ticker; - this.app.ticker = null; + app._ticker = _ticker as unknown as Ticker; + app.ticker = null; - expect(_ticker.remove).to.be.calledOnce; - expect(_ticker.remove.args[0][0]).to.be.equal(this.app.render); - expect(_ticker.remove.args[0][1]).to.be.equal(this.app); + expect(_ticker.remove).toHaveBeenCalledOnce(); + expect(_ticker.remove).toBeCalledWith(app.render, app); - expect(this.app._ticker).to.be.null; + expect(app._ticker).toBeNull(); }); }); }); diff --git a/packages/unsafe-eval/README.md b/packages/unsafe-eval/README.md index 62588645c77..8f6826e8812 100644 --- a/packages/unsafe-eval/README.md +++ b/packages/unsafe-eval/README.md @@ -10,7 +10,7 @@ npm install @pixi/unsafe-eval ## Usage -If you are using a bundler, you need to pass the core bundle into the `install` method. This function takes one arguments, either the global `PIXI` object, or the core. +If you are using a bundler, you need to pass the core bundle into the `install` method. ```js import { ShaderSystem, Renderer } from '@pixi/core'; @@ -23,9 +23,3 @@ install({ ShaderSystem }); const renderer = new Renderer(); ``` -If you are including **unsafe-eval.js** direct, you do not need to do anything else: - -```html - - -``` diff --git a/packages/unsafe-eval/package.json b/packages/unsafe-eval/package.json index 1d66de1ade3..7bbef89ab0c 100644 --- a/packages/unsafe-eval/package.json +++ b/packages/unsafe-eval/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/unsafe-eval", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/unsafe-eval.js", - "module": "dist/esm/unsafe-eval.js", - "bundle": "dist/browser/unsafe-eval.js", - "bundleInput": "src/bundle.ts", + "module": "dist/esm/unsafe-eval.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/unsafe-eval.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/unsafe-eval.js" + } + } + }, "standalone": true, "description": "Adds support for environments that disallow support of new Function", "author": "Matt Karl ", @@ -19,11 +30,10 @@ "access": "public" }, "files": [ - "lib/", "dist/", "*.d.ts" ], - "peerDependencies": { - "@pixi/core": "6.3.0" - } + "pixiRequirements": [ + "@pixi/core" + ] } diff --git a/packages/unsafe-eval/src/install.ts b/packages/unsafe-eval/src/install.ts index a54495ea077..0a8f485b25e 100644 --- a/packages/unsafe-eval/src/install.ts +++ b/packages/unsafe-eval/src/install.ts @@ -2,7 +2,8 @@ import { syncUniforms } from './syncUniforms'; import type { ShaderSystem, Program, UniformGroup } from '@pixi/core'; -interface PIXICore { +interface PIXICore +{ ShaderSystem: typeof ShaderSystem; } diff --git a/packages/utils/package.json b/packages/utils/package.json index f8cdc12d589..f54177a2000 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,10 +1,21 @@ { "name": "@pixi/utils", - "version": "6.3.0", + "version": "7.0.0-alpha", "main": "dist/cjs/utils.js", - "module": "dist/esm/utils.js", - "bundle": "dist/browser/utils.js", - "namespace": "PIXI.utils", + "module": "dist/esm/utils.mjs", + "types": "index.d.ts", + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./dist/esm/utils.mjs" + }, + "require": { + "types": "./index.d.ts", + "default": "./dist/cjs/utils.js" + } + } + }, "description": "Collection of utilities used by PixiJS", "author": "Mat Groves", "contributors": [ @@ -21,20 +32,17 @@ "access": "public" }, "files": [ - "lib", "dist", "*.d.ts" ], "dependencies": { + "@pixi/constants": "7.0.0-alpha", + "@pixi/settings": "7.0.0-alpha", "@types/earcut": "^2.1.0", - "earcut": "^2.2.2", + "earcut": "^2.2.4", "eventemitter3": "^3.1.0", "url": "^0.11.0" }, - "peerDependencies": { - "@pixi/constants": "6.3.0", - "@pixi/settings": "6.3.0" - }, "devDependencies": { "css-color-names": "^1.0.1" } diff --git a/packages/utils/src/browser/hello.ts b/packages/utils/src/browser/hello.ts index 240d1dd61d8..4f785462f78 100644 --- a/packages/utils/src/browser/hello.ts +++ b/packages/utils/src/browser/hello.ts @@ -1,9 +1,10 @@ +import { settings } from '@pixi/settings'; + let saidHello = false; const VERSION = '$_VERSION'; /** * Skips the hello message of renderers that are created after this is run. - * * @function skipHello * @memberof PIXI.utils */ @@ -16,7 +17,6 @@ export function skipHello(): void * Logs out the version and renderer information for this running instance of PIXI. * If you don't want to see this message you can run `PIXI.utils.skipHello()` before * creating your renderer. Keep in mind that doing that will forever make you a jerk face. - * * @static * @function sayHello * @memberof PIXI.utils @@ -29,7 +29,7 @@ export function sayHello(type: string): void return; } - if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) + if (settings.ADAPTER.getNavigator().userAgent.toLowerCase().indexOf('chrome') > -1) { const args = [ `\n %c %c %c PixiJS ${VERSION} - ✰ ${type} ✰ %c %c http://www.pixijs.com/ %c %c ♥%c♥%c♥ \n\n`, diff --git a/packages/utils/src/browser/isWebGLSupported.ts b/packages/utils/src/browser/isWebGLSupported.ts index 18890a1ef33..67759353c6c 100644 --- a/packages/utils/src/browser/isWebGLSupported.ts +++ b/packages/utils/src/browser/isWebGLSupported.ts @@ -1,13 +1,12 @@ import { settings } from '../settings'; -let supported: boolean|undefined; +let supported: boolean | undefined; /** * Helper for checking for WebGL support. - * * @memberof PIXI.utils * @function isWebGLSupported - * @return {boolean} Is WebGL supported. + * @returns {boolean} Is WebGL supported. */ export function isWebGLSupported(): boolean { @@ -22,12 +21,12 @@ export function isWebGLSupported(): boolean try { - if (!globalThis.WebGLRenderingContext) + if (!settings.ADAPTER.getWebGLRenderingContext()) { return false; } - const canvas = document.createElement('canvas'); + const canvas = settings.ADAPTER.createCanvas(); let gl = ( canvas.getContext('webgl', contextOptions) || canvas.getContext('experimental-webgl', contextOptions) diff --git a/packages/utils/src/color/hex.ts b/packages/utils/src/color/hex.ts index f05ff6f6396..b96042f7f9d 100644 --- a/packages/utils/src/color/hex.ts +++ b/packages/utils/src/color/hex.ts @@ -2,14 +2,13 @@ import { default as cssColorNames } from 'css-color-names'; /** * Converts a hexadecimal color number to an [R, G, B] array of normalized floats (numbers from 0.0 to 1.0). - * * @example * PIXI.utils.hex2rgb(0xffffff); // returns [1, 1, 1] * @memberof PIXI.utils * @function hex2rgb * @param {number} hex - The hexadecimal number to convert * @param {number[]} [out=[]] - If supplied, this array will be used rather than returning a new one - * @return {number[]} An array representing the [R, G, B] of the color where all values are floats. + * @returns {number[]} An array representing the [R, G, B] of the color where all values are floats. */ export function hex2rgb(hex: number, out: Array | Float32Array = []): Array | Float32Array { @@ -22,13 +21,12 @@ export function hex2rgb(hex: number, out: Array | Float32Array = []): Ar /** * Converts a hexadecimal color number to a string. - * * @example * PIXI.utils.hex2string(0xffffff); // returns "#ffffff" * @memberof PIXI.utils * @function hex2string * @param {number} hex - Number in hex (e.g., `0xffffff`) - * @return {string} The string color (e.g., `"#ffffff"`). + * @returns {string} The string color (e.g., `"#ffffff"`). */ export function hex2string(hex: number): string { @@ -46,13 +44,12 @@ export function hex2string(hex: number): string * hex strings starting with 0x: "0xffffff" * hex strings without prefix: "ffffff" * css colors: "black" - * * @example * PIXI.utils.string2hex("#ffffff"); // returns 0xffffff * @memberof PIXI.utils * @function string2hex * @param {string} string - The string color (e.g., `"#ffffff"`) - * @return {number} Number in hexadecimal. + * @returns {number} Number in hexadecimal. */ export function string2hex(string: string): number { @@ -71,13 +68,12 @@ export function string2hex(string: string): number /** * Converts a color as an [R, G, B] array of normalized floats to a hexadecimal number. - * * @example * PIXI.utils.rgb2hex([1, 1, 1]); // returns 0xffffff * @memberof PIXI.utils * @function rgb2hex * @param {number[]} rgb - Array of numbers where all values are normalized floats from 0.0 to 1.0. - * @return {number} Number in hexadecimal. + * @returns {number} Number in hexadecimal. */ export function rgb2hex(rgb: number[] | Float32Array): number { diff --git a/packages/utils/src/color/premultiply.ts b/packages/utils/src/color/premultiply.ts index 06cee17946b..dc347ed2d57 100644 --- a/packages/utils/src/color/premultiply.ts +++ b/packages/utils/src/color/premultiply.ts @@ -2,11 +2,10 @@ import { BLEND_MODES } from '@pixi/constants'; /** * Corrects PixiJS blend, takes premultiplied alpha into account - * * @memberof PIXI.utils * @function mapPremultipliedBlendModes * @private - * @return {Array} Mapped modes. + * @returns {Array} Mapped modes. */ function mapPremultipliedBlendModes(): number[][] { @@ -38,14 +37,13 @@ function mapPremultipliedBlendModes(): number[][] /** * maps premultiply flag and blendMode to adjusted blendMode * @memberof PIXI.utils - * @const premultiplyBlendMode + * @constant premultiplyBlendMode * @type {Array} */ export const premultiplyBlendMode = mapPremultipliedBlendModes(); /** * changes blendMode according to texture format - * * @memberof PIXI.utils * @function correctBlendMode * @param {number} blendMode - supposed blend mode @@ -59,7 +57,6 @@ export function correctBlendMode(blendMode: number, premultiplied: boolean): num /** * combines rgb and alpha to out array - * * @memberof PIXI.utils * @function premultiplyRgba * @param {Float32Array|number[]} rgb - input rgb @@ -69,7 +66,7 @@ export function correctBlendMode(blendMode: number, premultiplied: boolean): num * @returns {Float32Array} vec4 rgba */ export function premultiplyRgba( - rgb: Float32Array|number[], + rgb: Float32Array | number[], alpha: number, out?: Float32Array, premultiply?: boolean @@ -95,7 +92,6 @@ export function premultiplyRgba( /** * premultiplies tint - * * @memberof PIXI.utils * @function premultiplyTint * @param {number} tint - integer RGB @@ -125,7 +121,6 @@ export function premultiplyTint(tint: number, alpha: number): number /** * converts integer tint and float alpha to vec4 form, premultiplies by default - * * @memberof PIXI.utils * @function premultiplyTintToRgba * @param {number} tint - input tint diff --git a/packages/utils/src/const.ts b/packages/utils/src/const.ts index 5895fe1af9e..6e142ff28f8 100644 --- a/packages/utils/src/const.ts +++ b/packages/utils/src/const.ts @@ -1,7 +1,6 @@ /** * Regexp for data URI. * Based on: {@link https://github.com/ragingwind/data-uri-regex} - * * @static * @constant {RegExp|string} DATA_URI * @memberof PIXI diff --git a/packages/utils/src/data/createIndicesForQuads.ts b/packages/utils/src/data/createIndicesForQuads.ts index 8a15ef52eee..a6e88ddbd63 100644 --- a/packages/utils/src/data/createIndicesForQuads.ts +++ b/packages/utils/src/data/createIndicesForQuads.ts @@ -1,13 +1,12 @@ /** * Generic Mask Stack data structure - * * @memberof PIXI.utils * @function createIndicesForQuads * @param {number} size - Number of quads * @param {Uint16Array|Uint32Array} [outBuffer] - Buffer for output, length has to be `6 * size` - * @return {Uint16Array|Uint32Array} - Resulting index buffer + * @returns {Uint16Array|Uint32Array} - Resulting index buffer */ -export function createIndicesForQuads(size: number, outBuffer: Uint16Array|Uint32Array = null): Uint16Array|Uint32Array +export function createIndicesForQuads(size: number, outBuffer: Uint16Array | Uint32Array = null): Uint16Array | Uint32Array { // the total number of indices in our array, there are 6 points per quad. const totalIndices = size * 6; diff --git a/packages/utils/src/data/getBufferType.ts b/packages/utils/src/data/getBufferType.ts index bc103ae6f52..094edf270c2 100644 --- a/packages/utils/src/data/getBufferType.ts +++ b/packages/utils/src/data/getBufferType.ts @@ -1,6 +1,8 @@ import type { ITypedArray } from '@pixi/core'; -export function getBufferType(array: ITypedArray): 'Float32Array'|'Uint32Array'|'Int32Array'|'Uint16Array'|'Uint8Array'|null +export function getBufferType( + array: ITypedArray +): 'Float32Array' | 'Uint32Array' | 'Int32Array' | 'Uint16Array' | 'Uint8Array' | null { if (array.BYTES_PER_ELEMENT === 4) { diff --git a/packages/utils/src/data/interleaveTypedArrays.ts b/packages/utils/src/data/interleaveTypedArrays.ts index 54ae80d5d23..4e9c49d7ef8 100644 --- a/packages/utils/src/data/interleaveTypedArrays.ts +++ b/packages/utils/src/data/interleaveTypedArrays.ts @@ -3,7 +3,7 @@ import { getBufferType } from './getBufferType'; /* eslint-disable object-shorthand */ const map = { Float32Array: Float32Array, Uint32Array: Uint32Array, Int32Array: Int32Array, Uint8Array: Uint8Array }; -type PackedArray = Float32Array|Uint32Array|Int32Array|Uint8Array; +type PackedArray = Float32Array | Uint32Array | Int32Array | Uint8Array; export function interleaveTypedArrays(arrays: PackedArray[], sizes: number[]): Float32Array { diff --git a/packages/utils/src/data/pow2.ts b/packages/utils/src/data/pow2.ts index 35ec211c4d7..b7b44a61911 100644 --- a/packages/utils/src/data/pow2.ts +++ b/packages/utils/src/data/pow2.ts @@ -2,11 +2,10 @@ /** * Rounds to next power of two. - * * @function nextPow2 * @memberof PIXI.utils * @param {number} v - input value - * @return {number} + * @returns {number} - next rounded power of two */ export function nextPow2(v: number): number { @@ -23,11 +22,10 @@ export function nextPow2(v: number): number /** * Checks if a number is a power of two. - * * @function isPow2 * @memberof PIXI.utils * @param {number} v - input value - * @return {boolean} `true` if value is power of two + * @returns {boolean} `true` if value is power of two */ export function isPow2(v: number): boolean { @@ -36,11 +34,10 @@ export function isPow2(v: number): boolean /** * Computes ceil of log base 2 - * * @function log2 * @memberof PIXI.utils * @param {number} v - input value - * @return {number} logarithm base 2 + * @returns {number} logarithm base 2 */ export function log2(v: number): number { diff --git a/packages/utils/src/data/removeItems.ts b/packages/utils/src/data/removeItems.ts index 1f4ed6e0a54..6c739afa0f3 100644 --- a/packages/utils/src/data/removeItems.ts +++ b/packages/utils/src/data/removeItems.ts @@ -1,6 +1,5 @@ /** * Remove items from a javascript array without generating garbage - * * @function removeItems * @memberof PIXI.utils * @param {Array} arr - Array to remove elements from diff --git a/packages/utils/src/data/sign.ts b/packages/utils/src/data/sign.ts index 4e41c0d4eb5..06d763aae4c 100644 --- a/packages/utils/src/data/sign.ts +++ b/packages/utils/src/data/sign.ts @@ -1,12 +1,11 @@ /** * Returns sign of number - * * @memberof PIXI.utils * @function sign * @param {number} n - the number to check the sign of * @returns {number} 0 if `n` is 0, -1 if `n` is negative, 1 if `n` is positive */ -export function sign(n: number): -1|0|1 +export function sign(n: number): -1 | 0 | 1 { if (n === 0) return 0; diff --git a/packages/utils/src/data/uid.ts b/packages/utils/src/data/uid.ts index 6d5b00a8e08..416eb4fbb67 100644 --- a/packages/utils/src/data/uid.ts +++ b/packages/utils/src/data/uid.ts @@ -2,10 +2,9 @@ let nextUid = 0; /** * Gets the next unique identifier - * * @memberof PIXI.utils * @function uid - * @return {number} The next unique identifier to use. + * @returns {number} The next unique identifier to use. */ export function uid(): number { diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 5bde7ad712e..9270cdaa3aa 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -19,29 +19,27 @@ /** * A simple JS library that detects mobile devices. - * * @see {@link https://github.com/kaimallea/isMobile} - * * @memberof PIXI.utils * @name isMobile - * @member {Object} + * @member {object} * @property {boolean} any - `true` if current platform is tablet or phone device * @property {boolean} tablet - `true` if current platform large-screen tablet device * @property {boolean} phone - `true` if current platform small-screen phone device - * @property {object} apple + * @property {object} apple - * @property {boolean} apple.device - `true` if any Apple device * @property {boolean} apple.tablet - `true` if any Apple iPad * @property {boolean} apple.phone - `true` if any Apple iPhone * @property {boolean} apple.ipod - `true` if any iPod - * @property {object} android + * @property {object} android - * @property {boolean} android.device - `true` if any Android device * @property {boolean} android.tablet - `true` if any Android tablet * @property {boolean} android.phone - `true` if any Android phone - * @property {object} amazon + * @property {object} amazon - * @property {boolean} amazon.device - `true` if any Silk device * @property {boolean} amazon.tablet - `true` if any Silk tablet * @property {boolean} amazon.phone - `true` if any Silk phone - * @property {object} windows + * @property {object} windows - * @property {boolean} windows.device - `true` if any Windows device * @property {boolean} windows.tablet - `true` if any Windows tablet * @property {boolean} windows.phone - `true` if any Windows phone @@ -52,9 +50,7 @@ import EventEmitter from 'eventemitter3'; /** * A high performance event emitter - * * @see {@link https://github.com/primus/eventemitter3} - * * @memberof PIXI.utils * @class EventEmitter */ @@ -62,28 +58,32 @@ export { EventEmitter }; /** * A polygon triangulation library - * * @see {@link https://github.com/mapbox/earcut} - * * @memberof PIXI.utils * @method earcut * @param {number[]} vertices - A flat array of vertex coordinates * @param {number[]} [holes] - An array of hole indices * @param {number} [dimensions=2] - The number of coordinates per vertex in the input array - * @return {number[]} Triangulated polygon + * @returns {number[]} Triangulated polygon */ export { default as earcut } from 'earcut'; /** * Node.js compatible URL utilities. - * * @see https://www.npmjs.com/package/url - * * @memberof PIXI.utils * @name url * @member {object} */ export * from './url'; +/** + * Browser and Node.js compatible path utilities. + * All paths that are passed in will become normalized to have posix separators. + * @memberof PIXI.utils + * @name path + * @member {object} + */ +export * from './path'; import './settings'; diff --git a/packages/utils/src/logging/deprecation.ts b/packages/utils/src/logging/deprecation.ts index 54a55e8cff3..ed14f283340 100644 --- a/packages/utils/src/logging/deprecation.ts +++ b/packages/utils/src/logging/deprecation.ts @@ -7,7 +7,6 @@ const warnings: Dict = {}; * Helper for warning developers about deprecated features & settings. * A stack track for warnings is given; useful for tracking-down where * deprecated methods/properties/classes are being used within the code. - * * @memberof PIXI.utils * @function deprecation * @param {string} version - The version where the feature became deprecated diff --git a/packages/utils/src/media/CanvasRenderTarget.ts b/packages/utils/src/media/CanvasRenderTarget.ts index 13573b27286..40912fa95ac 100644 --- a/packages/utils/src/media/CanvasRenderTarget.ts +++ b/packages/utils/src/media/CanvasRenderTarget.ts @@ -2,7 +2,6 @@ import { settings } from '@pixi/settings'; /** * Creates a Canvas element of the given size to be used as a target for rendering to. - * * @class * @memberof PIXI.utils */ @@ -27,7 +26,7 @@ export class CanvasRenderTarget */ constructor(width: number, height: number, resolution?: number) { - this.canvas = document.createElement('canvas'); + this.canvas = settings.ADAPTER.createCanvas(); this.context = this.canvas.getContext('2d'); @@ -38,7 +37,6 @@ export class CanvasRenderTarget /** * Clears the canvas that was created by the CanvasRenderTarget class. - * * @private */ clear(): void @@ -49,7 +47,6 @@ export class CanvasRenderTarget /** * Resizes the canvas to the specified width and height. - * * @param desiredWidth - the desired width of the canvas * @param desiredHeight - the desired height of the canvas */ @@ -68,7 +65,6 @@ export class CanvasRenderTarget /** * The width of the canvas buffer in pixels. - * * @member {number} */ get width(): number @@ -83,7 +79,6 @@ export class CanvasRenderTarget /** * The height of the canvas buffer in pixels. - * * @member {number} */ get height(): number diff --git a/packages/utils/src/media/caches.ts b/packages/utils/src/media/caches.ts index 85a764756c8..21b7fe94ff2 100644 --- a/packages/utils/src/media/caches.ts +++ b/packages/utils/src/media/caches.ts @@ -2,37 +2,33 @@ import type { Program, Texture, BaseTexture } from '@pixi/core'; /** * @todo Describe property usage - * * @static * @name ProgramCache * @memberof PIXI.utils - * @type {Object} + * @type {object} */ export const ProgramCache: {[key: string]: Program} = {}; /** * @todo Describe property usage - * * @static * @name TextureCache * @memberof PIXI.utils - * @type {Object} + * @type {object} */ export const TextureCache: {[key: string]: Texture} = Object.create(null); /** * @todo Describe property usage - * * @static * @name BaseTextureCache * @memberof PIXI.utils - * @type {Object} + * @type {object} */ export const BaseTextureCache: {[key: string]: BaseTexture} = Object.create(null); /** * Destroys all texture in the cache - * * @memberof PIXI.utils * @function destroyTextureCache */ @@ -52,7 +48,6 @@ export function destroyTextureCache(): void /** * Removes all textures from cache, but does not destroy them - * * @memberof PIXI.utils * @function clearTextureCache */ diff --git a/packages/utils/src/media/trimCanvas.ts b/packages/utils/src/media/trimCanvas.ts index 5c1ef32a430..630a42773df 100644 --- a/packages/utils/src/media/trimCanvas.ts +++ b/packages/utils/src/media/trimCanvas.ts @@ -1,4 +1,5 @@ -interface Inset { +interface Inset +{ top?: number; left?: number; right?: number; @@ -7,7 +8,6 @@ interface Inset { /** * Trim transparent borders from a canvas - * * @memberof PIXI.utils * @function trimCanvas * @param {HTMLCanvasElement} canvas - the canvas to trim diff --git a/packages/utils/src/network/decomposeDataUri.ts b/packages/utils/src/network/decomposeDataUri.ts index 36642423116..c1662f8a9d3 100644 --- a/packages/utils/src/network/decomposeDataUri.ts +++ b/packages/utils/src/network/decomposeDataUri.ts @@ -1,6 +1,7 @@ import { DATA_URI } from '../const'; -export interface DecomposedDataUri { +export interface DecomposedDataUri +{ mediaType: string; subType: string; charset: string; @@ -45,11 +46,10 @@ export interface DecomposedDataUri { /** * Split a data URI into components. Returns undefined if * parameter `dataUri` is not a valid data URI. - * * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {PIXI.utils.DecomposedDataUri|undefined} The decomposed data uri or undefined + * @returns {PIXI.utils.DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri: string): DecomposedDataUri { diff --git a/packages/utils/src/network/determineCrossOrigin.ts b/packages/utils/src/network/determineCrossOrigin.ts index 0a73ffbfea3..97fa475142a 100644 --- a/packages/utils/src/network/determineCrossOrigin.ts +++ b/packages/utils/src/network/determineCrossOrigin.ts @@ -1,22 +1,21 @@ import { url as _url } from '../url'; -let tempAnchor: HTMLAnchorElement|undefined; +let tempAnchor: HTMLAnchorElement | undefined; /** * Sets the `crossOrigin` property for this resource based on if the url * for this resource is cross-origin. If crossOrigin was manually set, this * function does nothing. * Nipped from the resource loader! - * * @ignore * @param {string} url - The url to test. * @param {object} [loc=window.location] - The location object to test against. - * @return {string} The crossOrigin value to use (or empty string for none). + * @returns {string} The crossOrigin value to use (or empty string for none). */ export function determineCrossOrigin(url: string, loc: Location = globalThis.location): string { // data: and javascript: urls are considered same-origin - if (url.indexOf('data:') === 0) + if (url.startsWith('data:')) { return ''; } diff --git a/packages/utils/src/network/getResolutionOfUrl.ts b/packages/utils/src/network/getResolutionOfUrl.ts index d30d830aaa3..47a8ceeb213 100644 --- a/packages/utils/src/network/getResolutionOfUrl.ts +++ b/packages/utils/src/network/getResolutionOfUrl.ts @@ -3,14 +3,13 @@ import { settings } from '../settings'; /** * get the resolution / device pixel ratio of an asset by looking for the prefix * used by spritesheets and image urls - * * @memberof PIXI.utils * @function getResolutionOfUrl * @param {string} url - the image path * @param {number} [defaultValue=1] - the defaultValue if no filename prefix is set. - * @return {number} resolution / device pixel ratio of an asset + * @returns {number} resolution / device pixel ratio of an asset */ -export function getResolutionOfUrl(url: string, defaultValue?: number): number +export function getResolutionOfUrl(url: string, defaultValue = 1): number { const resolution = settings.RETINA_PREFIX.exec(url); @@ -19,5 +18,5 @@ export function getResolutionOfUrl(url: string, defaultValue?: number): number return parseFloat(resolution[1]); } - return defaultValue !== undefined ? defaultValue : 1; + return defaultValue; } diff --git a/packages/utils/src/path.ts b/packages/utils/src/path.ts new file mode 100644 index 00000000000..cfd4d79fba7 --- /dev/null +++ b/packages/utils/src/path.ts @@ -0,0 +1,681 @@ +import { settings } from '@pixi/settings'; + +function assertPath(path: string) +{ + if (typeof path !== 'string') + { + throw new TypeError(`Path must be a string. Received ${JSON.stringify(path)}`); + } +} + +function removeUrlParams(url: string): string +{ + const re = url.split('?')[0]; + + return re.split('#')[0]; +} + +function escapeRegExp(string: string) +{ + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +function replaceAll(str: string, find: string, replace: string) +{ + return str.replace(new RegExp(escapeRegExp(find), 'g'), replace); +} + +// Resolves . and .. elements in a path with directory names +function normalizeStringPosix(path: string, allowAboveRoot: boolean) +{ + let res = ''; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let code: number; + + for (let i = 0; i <= path.length; ++i) + { + if (i < path.length) + { + code = path.charCodeAt(i); + } + else if (code === 47) + { + break; + } + else + { + code = 47; + } + if (code === 47) + { + if (lastSlash === i - 1 || dots === 1) + { + // NOOP + } + else if (lastSlash !== i - 1 && dots === 2) + { + if ( + res.length < 2 + || lastSegmentLength !== 2 + || res.charCodeAt(res.length - 1) !== 46 + || res.charCodeAt(res.length - 2) !== 46 + ) + { + if (res.length > 2) + { + const lastSlashIndex = res.lastIndexOf('/'); + + if (lastSlashIndex !== res.length - 1) + { + if (lastSlashIndex === -1) + { + res = ''; + lastSegmentLength = 0; + } + else + { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); + } + lastSlash = i; + dots = 0; + continue; + } + } + else if (res.length === 2 || res.length === 1) + { + res = ''; + lastSegmentLength = 0; + lastSlash = i; + dots = 0; + continue; + } + } + if (allowAboveRoot) + { + if (res.length > 0) + { res += '/..'; } + else + { res = '..'; } + lastSegmentLength = 2; + } + } + else + { + if (res.length > 0) + { + res += `/${path.slice(lastSlash + 1, i)}`; + } + else + { + res = path.slice(lastSlash + 1, i); + } + lastSegmentLength = i - lastSlash - 1; + } + lastSlash = i; + dots = 0; + } + else if (code === 46 && dots !== -1) + { + ++dots; + } + else + { + dots = -1; + } + } + + return res; +} + +export interface Path +{ + toPosix: (path: string) => string; + toAbsolute: (url: string, baseUrl?: string, rootUrl?: string) => string; + isUrl: (path: string) => boolean; + isDataUrl: (path: string) => boolean; + hasProtocol: (path: string) => boolean; + getProtocol: (path: string) => string; + normalize: (path: string) => string; + join: (...paths: string[]) => string; + isAbsolute: (path: string) => boolean; + dirname: (path: string) => string; + rootname: (path: string) => string; + basename: (path: string, ext?: string) => string; + extname: (path: string) => string; + parse: (path: string) => { root?: string, dir?: string, base?: string, ext?: string, name?: string }; + sep: string, + delimiter: string +} + +export const path: Path = { + /** + * Converts a path to posix format. + * @param path - The path to convert to posix + */ + toPosix(path: string) { return replaceAll(path, '\\', '/'); }, + /** + * Checks if the path is a URL + * @param path - The path to check + */ + isUrl(path: string) { return (/^https?:/).test(this.toPosix(path)); }, + /** + * Checks if the path is a data URL + * @param path - The path to check + */ + isDataUrl(path: string) + { + // eslint-disable-next-line max-len + return (/^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i) + .test(path); + }, + /** + * Checks if the path has a protocol e.g. http:// + * This will return true for windows file paths + * @param path - The path to check + */ + hasProtocol(path: string) { return (/^[^/:]+:\//).test(this.toPosix(path)); }, + /** + * Returns the protocol of the path e.g. http://, C:/, file:/// + * @param path - The path to get the protocol from + */ + getProtocol(path: string) + { + assertPath(path); + path = this.toPosix(path); + + let protocol = ''; + + const isFile = (/^file:\/\/\//).exec(path); + const isHttp = (/^[^/:]+:\/\//).exec(path); + const isWindows = (/^[^/:]+:\//).exec(path); + + if (isFile || isHttp || isWindows) + { + const arr = isFile?.[0] || isHttp?.[0] || isWindows?.[0]; + + protocol = arr; + path = path.slice(arr.length); + } + + return protocol; + }, + + /** + * Converts URL to an absolute path. + * When loading from a Web Worker, we must use absolute paths. + * If the URL is already absolute we return it as is + * If it's not, we convert it + * @param url - The URL to test + * @param customBaseUrl - The base URL to use + * @param customRootUrl - The root URL to use + */ + toAbsolute(url: string, customBaseUrl?: string, customRootUrl?: string) + { + if (this.isDataUrl(url)) return url; + + const baseUrl = removeUrlParams(this.toPosix(customBaseUrl ?? settings.ADAPTER.getBaseUrl())); + const rootUrl = removeUrlParams(this.toPosix(customRootUrl ?? this.rootname(baseUrl))); + + assertPath(url); + url = this.toPosix(url); + + // root relative url + if (url.startsWith('/')) + { + return path.join(rootUrl, url.slice(1)); + } + + const absolutePath = this.isAbsolute(url) ? url : this.join(baseUrl, url); + + return absolutePath; + }, + + /** + * Normalizes the given path, resolving '..' and '.' segments + * @param path - The path to normalize + */ + normalize(path: string) + { + path = this.toPosix(path); + assertPath(path); + + if (path.length === 0) return '.'; + + let protocol = ''; + const isAbsolute = path.startsWith('/'); + + if (this.hasProtocol(path)) + { + protocol = this.rootname(path); + path = path.slice(protocol.length); + } + + const trailingSeparator = path.endsWith('/'); + + // Normalize the path + path = normalizeStringPosix(path, false); + + if (path.length > 0 && trailingSeparator) path += '/'; + if (isAbsolute) return `/${path}`; + + return protocol + path; + }, + + /** + * Determines if path is an absolute path. + * Absolute paths can be urls, data urls, or paths on disk + * @param path - The path to test + */ + isAbsolute(path: string) + { + assertPath(path); + path = this.toPosix(path); + + if (this.hasProtocol(path)) return true; + + return path.startsWith('/'); + }, + + /** + * Joins all given path segments together using the platform-specific separator as a delimiter, + * then normalizes the resulting path + * @param segments - The segments of the path to join + */ + join(...segments: string[]) + { + if (segments.length === 0) + { return '.'; } + let joined; + + for (let i = 0; i < segments.length; ++i) + { + const arg = segments[i]; + + assertPath(arg); + if (arg.length > 0) + { + if (joined === undefined) joined = arg; + else + { + const prevArg = segments[i - 1] ?? ''; + + if (this.extname(prevArg)) + { + joined += `/../${arg}`; + } + else + { + joined += `/${arg}`; + } + } + } + } + if (joined === undefined) { return '.'; } + + return this.normalize(joined); + }, + + /** + * Returns the directory name of a path + * @param path - The path to parse + */ + dirname(path: string) + { + assertPath(path); + if (path.length === 0) return '.'; + path = this.toPosix(path); + let code = path.charCodeAt(0); + const hasRoot = code === 47; + let end = -1; + let matchedSlash = true; + + const proto = this.getProtocol(path); + const origpath = path; + + path = path.slice(proto.length); + + for (let i = path.length - 1; i >= 1; --i) + { + code = path.charCodeAt(i); + if (code === 47) + { + if (!matchedSlash) + { + end = i; + break; + } + } + else + { + // We saw the first non-path separator + matchedSlash = false; + } + } + + // if end is -1 and its a url then we need to add the path back + // eslint-disable-next-line no-nested-ternary + if (end === -1) return hasRoot ? '/' : this.isUrl(origpath) ? proto + path : proto; + if (hasRoot && end === 1) return '//'; + + return proto + path.slice(0, end); + }, + + /** + * Returns the root of the path e.g. /, C:/, file:///, http://domain.com/ + * @param path - The path to parse + */ + rootname(path: string) + { + assertPath(path); + path = this.toPosix(path); + + let root = ''; + + if (path.startsWith('/')) root = '/'; + else + { + root = this.getProtocol(path); + } + + if (this.isUrl(path)) + { + // need to find the first path separator + const index = path.indexOf('/', root.length); + + if (index !== -1) + { + root = path.slice(0, index); + } + else root = path; + + if (!root.endsWith('/')) root += '/'; + } + + return root; + }, + + /** + * Returns the last portion of a path + * @param path - The path to test + * @param ext - Optional extension to remove + */ + basename(path: string, ext?: string) + { + assertPath(path); + if (ext) assertPath(ext); + + path = this.toPosix(path); + + let start = 0; + let end = -1; + let matchedSlash = true; + let i: number; + + if (ext !== undefined && ext.length > 0 && ext.length <= path.length) + { + if (ext.length === path.length && ext === path) return ''; + let extIdx = ext.length - 1; + let firstNonSlashEnd = -1; + + for (i = path.length - 1; i >= 0; --i) + { + const code = path.charCodeAt(i); + + if (code === 47) + { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) + { + start = i + 1; + break; + } + } + else + { + if (firstNonSlashEnd === -1) + { + // We saw the first non-path separator, remember this index in case + // we need it if the extension ends up not matching + matchedSlash = false; + firstNonSlashEnd = i + 1; + } + if (extIdx >= 0) + { + // Try to match the explicit extension + if (code === ext.charCodeAt(extIdx)) + { + if (--extIdx === -1) + { + // We matched the extension, so mark this as the end of our path + // component + end = i; + } + } + else + { + // Extension does not match, so our result is the entire path + // component + extIdx = -1; + end = firstNonSlashEnd; + } + } + } + } + + if (start === end) end = firstNonSlashEnd; else if (end === -1) end = path.length; + + return path.slice(start, end); + } + for (i = path.length - 1; i >= 0; --i) + { + if (path.charCodeAt(i) === 47) + { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) + { + start = i + 1; + break; + } + } + else if (end === -1) + { + // We saw the first non-path separator, mark this as the end of our + // path component + matchedSlash = false; + end = i + 1; + } + } + + if (end === -1) return ''; + + return path.slice(start, end); + }, + + /** + * Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last + * portion of the path. If there is no . in the last portion of the path, or if there are no . characters other than + * the first character of the basename of path, an empty string is returned. + * @param path - The path to parse + */ + extname(path: string) + { + assertPath(path); + path = this.toPosix(path); + + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + for (let i = path.length - 1; i >= 0; --i) + { + const code = path.charCodeAt(i); + + if (code === 47) + { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) + { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) + { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === 46) + { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) startDot = i; + else if (preDotState !== 1) preDotState = 1; + } + else if (startDot !== -1) + { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if ( + startDot === -1 || end === -1 + // We saw a non-dot character immediately before the dot + || preDotState === 0 + // The (right-most) trimmed path component is exactly '..' + // eslint-disable-next-line no-mixed-operators + || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1 + ) + { + return ''; + } + + return path.slice(startDot, end); + }, + + /** + * Parses a path into an object containing the 'root', `dir`, `base`, `ext`, and `name` properties. + * @param path - The path to parse + */ + parse(path: string) + { + assertPath(path); + + const ret = { root: '', dir: '', base: '', ext: '', name: '' }; + + if (path.length === 0) return ret; + path = this.toPosix(path); + + let code = path.charCodeAt(0); + const isAbsolute = this.isAbsolute(path); + let start: number; + const protocol = ''; + + ret.root = this.rootname(path); + + if (isAbsolute || this.hasProtocol(path)) + { + start = 1; + } + else + { + start = 0; + } + let startDot = -1; + let startPart = 0; + let end = -1; + let matchedSlash = true; + let i = path.length - 1; + + // Track the state of characters (if any) we see before our first dot and + // after any path separator we find + let preDotState = 0; + + // Get non-dir info + for (; i >= start; --i) + { + code = path.charCodeAt(i); + if (code === 47) + { + // If we reached a path separator that was not part of a set of path + // separators at the end of the string, stop now + if (!matchedSlash) + { + startPart = i + 1; + break; + } + continue; + } + if (end === -1) + { + // We saw the first non-path separator, mark this as the end of our + // extension + matchedSlash = false; + end = i + 1; + } + if (code === 46) + { + // If this is our first dot, mark it as the start of our extension + if (startDot === -1) startDot = i; + else if (preDotState !== 1) preDotState = 1; + } + else if (startDot !== -1) + { + // We saw a non-dot and non-path separator before our dot, so we should + // have a good chance at having a non-empty extension + preDotState = -1; + } + } + + if ( + startDot === -1 || end === -1 + // We saw a non-dot character immediately before the dot + || preDotState === 0 + // The (right-most) trimmed path component is exactly '..' + // eslint-disable-next-line no-mixed-operators + || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1 + ) + { + if (end !== -1) + { + if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end); + else ret.base = ret.name = path.slice(startPart, end); + } + } + else + { + if (startPart === 0 && isAbsolute) + { + ret.name = path.slice(1, startDot); + ret.base = path.slice(1, end); + } + else + { + ret.name = path.slice(startPart, startDot); + ret.base = path.slice(startPart, end); + } + ret.ext = path.slice(startDot, end); + } + + ret.dir = this.dirname(path); + if (protocol) ret.dir = protocol + ret.dir; + + return ret; + }, + + sep: '/', + delimiter: ':' +} as Path; diff --git a/packages/utils/src/settings.ts b/packages/utils/src/settings.ts index 07699ca5f77..a19bec52351 100644 --- a/packages/utils/src/settings.ts +++ b/packages/utils/src/settings.ts @@ -2,7 +2,6 @@ import { settings } from '@pixi/settings'; /** * The prefix that denotes a URL is for a retina asset. - * * @static * @name RETINA_PREFIX * @memberof PIXI.settings @@ -31,7 +30,6 @@ settings.RETINA_PREFIX = /@([0-9\.]+)x/; * renderer, and show an error message to the user if the function returns false, explaining that their device & browser * combination does not support high performance WebGL. * This is a much better strategy than trying to create a PixiJS renderer and finding it then fails. - * * @static * @name FAIL_IF_MAJOR_PERFORMANCE_CAVEAT * @memberof PIXI.settings diff --git a/packages/utils/src/url.ts b/packages/utils/src/url.ts index 57c0e9d48c1..1763e988469 100644 --- a/packages/utils/src/url.ts +++ b/packages/utils/src/url.ts @@ -7,15 +7,18 @@ import { parse as _parse, format as _format, resolve as _resolve } from 'url'; -interface ParsedUrlQuery { +interface ParsedUrlQuery +{ [key: string]: string | string[]; } -interface ParsedUrlQueryInput { +interface ParsedUrlQueryInput +{ [key: string]: unknown; } -interface UrlObjectCommon { +interface UrlObjectCommon +{ auth?: string; hash?: string; host?: string; @@ -29,26 +32,31 @@ interface UrlObjectCommon { } // Input to `url.format` -interface UrlObject extends UrlObjectCommon { +interface UrlObject extends UrlObjectCommon +{ port?: string | number; query?: string | null | ParsedUrlQueryInput; } // Output of `url.parse` -interface Url extends UrlObjectCommon { +interface Url extends UrlObjectCommon +{ port?: string; query?: string | null | ParsedUrlQuery; } -interface UrlWithParsedQuery extends Url { +interface UrlWithParsedQuery extends Url +{ query: ParsedUrlQuery; } -interface UrlWithStringQuery extends Url { +interface UrlWithStringQuery extends Url +{ query: string | null; } -interface URLFormatOptions { +interface URLFormatOptions +{ auth?: boolean; fragment?: boolean; search?: boolean; diff --git a/packages/utils/test/CanvasRenderTarget.tests.ts b/packages/utils/test/CanvasRenderTarget.tests.ts index ab49167e8d0..e8825060a0f 100644 --- a/packages/utils/test/CanvasRenderTarget.tests.ts +++ b/packages/utils/test/CanvasRenderTarget.tests.ts @@ -1,53 +1,52 @@ import { CanvasRenderTarget } from '@pixi/utils'; import { settings } from '@pixi/settings'; -import { expect } from 'chai'; -describe('CanvasRenderTarget', function () +describe('CanvasRenderTarget', () => { - it('should create with default resolution', function () + it('should create with default resolution', () => { const renderTarget = new CanvasRenderTarget(200, 100); - expect(renderTarget.canvas).to.be.instanceOf(HTMLCanvasElement); - expect(renderTarget.width).to.equal(200); - expect(renderTarget.height).to.equal(100); - expect(renderTarget.resolution).to.equal(settings.RESOLUTION); - expect(renderTarget.canvas.width).to.equal(200 * settings.RESOLUTION); - expect(renderTarget.canvas.height).to.equal(100 * settings.RESOLUTION); + expect(renderTarget.canvas).toBeInstanceOf(HTMLCanvasElement); + expect(renderTarget.width).toEqual(200); + expect(renderTarget.height).toEqual(100); + expect(renderTarget.resolution).toEqual(settings.RESOLUTION); + expect(renderTarget.canvas.width).toEqual(200 * settings.RESOLUTION); + expect(renderTarget.canvas.height).toEqual(100 * settings.RESOLUTION); renderTarget.destroy(); - expect(renderTarget.canvas).to.be.null; + expect(renderTarget.canvas).toBeNull(); }); - it('should create with custom resolution', function () + it('should create with custom resolution', () => { const renderTarget = new CanvasRenderTarget(200, 100, 2); - expect(renderTarget.canvas).to.be.instanceOf(HTMLCanvasElement); - expect(renderTarget.width).to.equal(400); - expect(renderTarget.height).to.equal(200); - expect(renderTarget.resolution).to.equal(2); - expect(renderTarget.canvas.width).to.equal(400); - expect(renderTarget.canvas.height).to.equal(200); + expect(renderTarget.canvas).toBeInstanceOf(HTMLCanvasElement); + expect(renderTarget.width).toEqual(400); + expect(renderTarget.height).toEqual(200); + expect(renderTarget.resolution).toEqual(2); + expect(renderTarget.canvas.width).toEqual(400); + expect(renderTarget.canvas.height).toEqual(200); renderTarget.destroy(); }); - it('should manually set width and height', function () + it('should manually set width and height', () => { const renderTarget = new CanvasRenderTarget(200, 100); renderTarget.width = 400; renderTarget.height = 200; - expect(renderTarget.canvas.width).to.equal(400); - expect(renderTarget.canvas.height).to.equal(200); + expect(renderTarget.canvas.width).toEqual(400); + expect(renderTarget.canvas.height).toEqual(200); renderTarget.destroy(); }); - it('should clear successfully', function () + it('should clear successfully', () => { const renderTarget = new CanvasRenderTarget(200, 100); diff --git a/packages/utils/test/TextureCache.tests.ts b/packages/utils/test/TextureCache.tests.ts index 0978b620c95..b870392aea3 100644 --- a/packages/utils/test/TextureCache.tests.ts +++ b/packages/utils/test/TextureCache.tests.ts @@ -1,23 +1,22 @@ import { Texture, BaseTexture } from '@pixi/core'; import { TextureCache, destroyTextureCache, clearTextureCache, BaseTextureCache } from '@pixi/utils'; -import { expect } from 'chai'; -describe('TextureCache', function () +describe('TextureCache', () => { - beforeEach(function () + beforeEach(() => { destroyTextureCache(); clearTextureCache(); }); - it('should exist', function () + it('should exist', () => { - expect(TextureCache).to.be.an('object'); + expect(TextureCache).toBeObject(); }); - describe('destroyTextureCache', function () + describe('destroyTextureCache', () => { - it('should successfully destroy the texture cache', function () + it('should successfully destroy the texture cache', () => { const canvas = document.createElement('canvas'); const foo = new Texture(new BaseTexture(canvas)); @@ -28,26 +27,26 @@ describe('TextureCache', function () BaseTextureCache.foo = foo.baseTexture; BaseTextureCache.bar = bar.baseTexture; - expect(Object.keys(TextureCache).length).to.equal(2); - expect(Object.keys(BaseTextureCache).length).to.equal(2); + expect(Object.keys(TextureCache).length).toEqual(2); + expect(Object.keys(BaseTextureCache).length).toEqual(2); destroyTextureCache(); - expect(Object.keys(TextureCache).length).to.equal(2); - expect(Object.keys(BaseTextureCache).length).to.equal(2); - expect(foo.baseTexture).to.be.null; - expect(bar.baseTexture).to.be.null; + expect(Object.keys(TextureCache).length).toEqual(2); + expect(Object.keys(BaseTextureCache).length).toEqual(2); + expect(foo.baseTexture).toBeNull(); + expect(bar.baseTexture).toBeNull(); clearTextureCache(); - expect(Object.keys(TextureCache).length).to.equal(0); - expect(Object.keys(BaseTextureCache).length).to.equal(0); + expect(Object.keys(TextureCache).length).toEqual(0); + expect(Object.keys(BaseTextureCache).length).toEqual(0); }); }); - describe('clearTextureCache', function () + describe('clearTextureCache', () => { - it('should successfully clear the texture cache', function () + it('should successfully clear the texture cache', () => { const canvas = document.createElement('canvas'); const foo = new Texture(new BaseTexture(canvas)); @@ -58,15 +57,15 @@ describe('TextureCache', function () BaseTextureCache.foo = foo.baseTexture; BaseTextureCache.bar = bar.baseTexture; - expect(Object.keys(TextureCache).length).to.equal(2); - expect(Object.keys(BaseTextureCache).length).to.equal(2); + expect(Object.keys(TextureCache).length).toEqual(2); + expect(Object.keys(BaseTextureCache).length).toEqual(2); clearTextureCache(); - expect(Object.keys(TextureCache).length).to.equal(0); - expect(Object.keys(BaseTextureCache).length).to.equal(0); - expect(foo.baseTexture).to.be.instanceOf(BaseTexture); - expect(bar.baseTexture).to.be.instanceOf(BaseTexture); + expect(Object.keys(TextureCache).length).toEqual(0); + expect(Object.keys(BaseTextureCache).length).toEqual(0); + expect(foo.baseTexture).toBeInstanceOf(BaseTexture); + expect(bar.baseTexture).toBeInstanceOf(BaseTexture); foo.destroy(true); bar.destroy(true); diff --git a/packages/utils/test/path.tests.ts b/packages/utils/test/path.tests.ts new file mode 100644 index 00000000000..38f2e1fa3be --- /dev/null +++ b/packages/utils/test/path.tests.ts @@ -0,0 +1,316 @@ +import { path } from '@pixi/utils'; + +describe('Paths', () => +{ + it('should convert paths to posix', () => + { + expect(path.toPosix('C:\\foo\\bar')).toBe('C:/foo/bar'); + expect(path.toPosix('C:\\foo\\bar/')).toBe('C:/foo/bar/'); + expect(path.toPosix('C:\\foo/bar')).toBe('C:/foo/bar'); + expect(path.toPosix('foo\\bar')).toBe('foo/bar'); + expect(path.toPosix('foo\\bar/baz')).toBe('foo/bar/baz'); + }); + + it('should check if path is a url', () => + { + expect(path.isUrl('http://foo.com')).toBe(true); + expect(path.isUrl('https://foo.com')).toBe(true); + expect(path.isUrl('http://foo.com/bar/baz')).toBe(true); + expect(path.isUrl('https://foo.com/bar/baz')).toBe(true); + expect(path.isUrl('https://foo.com/bar/baz/')).toBe(true); + expect(path.isUrl('file:///foo/bar/baz')).toBe(false); + expect(path.isUrl('//foo.com')).toBe(false); + expect(path.isUrl('foo.com')).toBe(false); + expect(path.isUrl('/foo.com')).toBe(false); + expect(path.isUrl('foo/bar')).toBe(false); + expect(path.isUrl('C:/foo/bar')).toBe(false); + expect(path.isUrl('C:\\foo\\bar')).toBe(false); + }); + + it('should check if a path contains a protocol', () => + { + expect(path.hasProtocol('http://foo.com')).toBe(true); + expect(path.hasProtocol('https://foo.com')).toBe(true); + expect(path.hasProtocol('https://foo.com/')).toBe(true); + expect(path.hasProtocol('file:///foo/bar/baz')).toBe(true); + expect(path.hasProtocol('C:/foo/bar')).toBe(true); + expect(path.hasProtocol('C:\\foo\\bar')).toBe(true); + + expect(path.hasProtocol('//foo.com')).toBe(false); + expect(path.hasProtocol('foo.com')).toBe(false); + expect(path.hasProtocol('/foo.com')).toBe(false); + expect(path.hasProtocol('foo/bar')).toBe(false); + }); + + it('should extract the protocol from a url', () => + { + expect(path.getProtocol('http://foo.com')).toBe('http://'); + expect(path.getProtocol('https://foo.com')).toBe('https://'); + expect(path.getProtocol('https://foo.com/')).toBe('https://'); + expect(path.getProtocol('file:///foo/bar/baz')).toBe('file:///'); + expect(path.getProtocol('C:/foo/bar')).toBe('C:/'); + expect(path.getProtocol('C:\\foo\\bar')).toBe('C:/'); + expect(path.getProtocol('/foo/bar/baz')).toBe(''); + expect(path.getProtocol('foo\\bar\\baz')).toBe(''); + }); + + it('should state if a path is absolute or not', () => + { + expect(path.isAbsolute('/foo/bar')).toBe(true); + expect(path.isAbsolute('/foo/bar/')).toBe(true); + expect(path.isAbsolute('C:\\foo\\bar')).toBe(true); + expect(path.isAbsolute('C:/foo/bar')).toBe(true); + expect(path.isAbsolute('C:/foo/bar/')).toBe(true); + expect(path.isAbsolute('http://foo.com/bar/baz')).toBe(true); + expect(path.isAbsolute('https://foo.com/bar/baz')).toBe(true); + expect(path.isAbsolute('https://foo.com/bar/baz/')).toBe(true); + expect(path.isAbsolute('file:///foo/bar/baz')).toBe(true); + expect(path.isAbsolute('foo/bar')).toBe(false); + expect(path.isAbsolute('foo/bar/')).toBe(false); + expect(path.isAbsolute('foo\\bar')).toBe(false); + expect(path.isAbsolute('../foo/bar')).toBe(false); + expect(path.isAbsolute('./foo/bar')).toBe(false); + }); + + it('should normalise the path', () => + { + expect(path.normalize('https://foo.com/bar/baz//file')).toBe('https://foo.com/bar/baz/file'); + expect(path.normalize('https://foo.com/bar/baz/../file')).toBe('https://foo.com/bar/file'); + expect(path.normalize('https://foo.com/../bar/baz//file')).toBe('https://foo.com/bar/baz/file'); + expect(path.normalize('https://foo.com/../../bar/baz//file')).toBe('https://foo.com/bar/baz/file'); + expect(path.normalize('https://foo.com/../../../../../bar/baz//file')).toBe('https://foo.com/bar/baz/file'); + expect(path.normalize('file:///foo/../../../../../bar/baz//file')).toBe('file:///bar/baz/file'); + expect(path.normalize('C:/foo/../../../../../bar/baz//file')).toBe('C:/bar/baz/file'); + expect(path.normalize('/foo/../../../../../bar/baz//file')).toBe('/bar/baz/file'); + expect(path.normalize('file:///foo/bar/baz//file')).toBe('file:///foo/bar/baz/file'); + expect(path.normalize('C:\\foo\\bar\\baz\\file')).toBe('C:/foo/bar/baz/file'); + expect(path.normalize('C:/foo\\bar\\baz\\file')).toBe('C:/foo/bar/baz/file'); + expect(path.normalize('/foo/bar/baz/file')).toBe('/foo/bar/baz/file'); + expect(path.normalize('foo')).toBe('foo'); + }); + + it('should join paths', () => + { + expect(path.join('http://foo.com/index.html', '../bar/baz/file')).toBe('http://foo.com/bar/baz/file'); + expect(path.join('http://foo.com/bar/index.html', '../baz/file')).toBe('http://foo.com/baz/file'); + expect(path.join('http://foo.com/bar/index.html', './baz/file')).toBe('http://foo.com/bar/baz/file'); + expect(path.join('http://foo.com/bar/index.html', 'baz/file')).toBe('http://foo.com/bar/baz/file'); + expect(path.join('http://foo.com/bar/index.html?var=a', '../baz/file')).toBe('http://foo.com/baz/file'); + expect(path.join('http://foo.com/bar/index.html?var=a#hash', '../baz/file')).toBe('http://foo.com/baz/file'); + expect(path.join('http://foo.com/bar/index.html#hash', '../baz/file')).toBe('http://foo.com/baz/file'); + + expect(path.join('http://foo.com', '../bar/baz/file')).toBe('http://foo.com/bar/baz/file'); + expect(path.join('https://foo.com', '../bar/baz/file')).toBe('https://foo.com/bar/baz/file'); + expect(path.join('file:///foo', '../bar/baz/file')).toBe('file:///bar/baz/file'); + expect(path.join('/foo', '../bar/baz/file')).toBe('/bar/baz/file'); + expect(path.join('C:/foo', '../bar/baz/file')).toBe('C:/bar/baz/file'); + expect(path.join('C:\\foo', '..\\bar\\baz\\file')).toBe('C:/bar/baz/file'); + + expect(path.join('http://foo.com', '../../bar/baz/file')).toBe('http://foo.com/bar/baz/file'); + expect(path.join('https://foo.com', '../../bar/baz/file')).toBe('https://foo.com/bar/baz/file'); + expect(path.join('file:///foo', '../../bar/baz/file')).toBe('file:///bar/baz/file'); + expect(path.join('/foo', '../../bar/baz/file')).toBe('/bar/baz/file'); + expect(path.join('C:/foo', '../../bar/baz/file')).toBe('C:/bar/baz/file'); + expect(path.join('C:\\foo', '..\\..\\bar\\baz\\file')).toBe('C:/bar/baz/file'); + + expect(path.join('http://foo.com', 'bar/baz/file', '../test')).toBe('http://foo.com/bar/baz/test'); + expect(path.join('https://foo.com', 'bar/baz/file', '../test')).toBe('https://foo.com/bar/baz/test'); + expect(path.join('file:///foo', 'bar/baz/file', '../test')).toBe('file:///foo/bar/baz/test'); + expect(path.join('/foo', 'bar/baz/file', '../test')).toBe('/foo/bar/baz/test'); + expect(path.join('C:/foo', 'bar/baz/file', '../test')).toBe('C:/foo/bar/baz/test'); + expect(path.join('C:\\foo', 'bar/baz/file', '../test')).toBe('C:/foo/bar/baz/test'); + }); + + it('should get the directory name', () => + { + expect(path.dirname('C:\\domain/')).toBe('C:/'); + expect(path.dirname('C:/domain/')).toBe('C:/'); + expect(path.dirname('/domain')).toBe('/'); + expect(path.dirname('C:\\')).toBe('C:/'); + expect(path.dirname('C:/')).toBe('C:/'); + expect(path.dirname('/')).toBe('/'); + expect(path.dirname('http://domain.com/')).toBe('http://domain.com/'); + expect(path.dirname('file:///domain/')).toBe('file:///'); + expect(path.dirname('C:\\domain/path')).toBe('C:/domain'); + expect(path.dirname('C:/domain/path')).toBe('C:/domain'); + expect(path.dirname('/domain/path')).toBe('/domain'); + expect(path.dirname('http://domain.com/path')).toBe('http://domain.com'); + expect(path.dirname('file:///domain/path')).toBe('file:///domain'); + expect(path.dirname('C:\\domain/path/to/file')).toBe('C:/domain/path/to'); + expect(path.dirname('C:/domain/path/to/file')).toBe('C:/domain/path/to'); + expect(path.dirname('/domain/path/to/file')).toBe('/domain/path/to'); + expect(path.dirname('http://domain.com/path/to/file')).toBe('http://domain.com/path/to'); + expect(path.dirname('file:///domain/path/to/file')).toBe('file:///domain/path/to'); + expect(path.dirname('domain.com/path/to/file')).toBe('domain.com/path/to'); + expect(path.dirname('domain')).toBe(''); + }); + + it('should get the root of a path', () => + { + expect(path.rootname('https://domain.com')).toBe('https://domain.com/'); + expect(path.rootname('/domain')).toBe('/'); + expect(path.rootname('C:/domain')).toBe('C:/'); + expect(path.rootname('https://domain.com/path')).toBe('https://domain.com/'); + expect(path.rootname('https://domain.com/')).toBe('https://domain.com/'); + expect(path.rootname('file:///domain')).toBe('file:///'); + expect(path.rootname('/domain.com')).toBe('/'); + expect(path.rootname('C:/domain/path')).toBe('C:/'); + }); + + it('should get the basename of a path', () => + { + expect(path.basename('https://foo.com/bar/baz/file.txt')).toBe('file.txt'); + expect(path.basename('file:///foo.com/bar/baz/file.txt')).toBe('file.txt'); + expect(path.basename('C:/foo/bar/baz/file.txt')).toBe('file.txt'); + expect(path.basename('C:\\foo\\bar\\bar\\file.txt')).toBe('file.txt'); + expect(path.basename('/foo/bar/baz/file.txt')).toBe('file.txt'); + expect(path.basename('foo/bar/baz/file.txt')).toBe('file.txt'); + + expect(path.basename('https://foo.com/bar/baz/file.txt', '.txt')).toBe('file'); + expect(path.basename('file:///foo/bar/baz/file.txt', '.txt')).toBe('file'); + expect(path.basename('C:/foo/bar/baz/file.txt', '.txt')).toBe('file'); + expect(path.basename('C:\\foo\\bar\\bar\\file.txt', '.txt')).toBe('file'); + expect(path.basename('/foo/bar/baz/file.txt', '.txt')).toBe('file'); + expect(path.basename('foo/bar/baz/file.txt', '.txt')).toBe('file'); + }); + + it('should get the extension of a path', () => + { + expect(path.extname('https://foo.com/bar/baz/file.txt')).toBe('.txt'); + expect(path.extname('file:///foo/bar/baz/file.txt')).toBe('.txt'); + expect(path.extname('C:/foo/bar/baz/file.txt')).toBe('.txt'); + expect(path.extname('C:\\foo\\bar\\bar\\file.txt')).toBe('.txt'); + expect(path.extname('/foo/bar/baz/file.txt')).toBe('.txt'); + expect(path.extname('foo/bar/baz/file.txt')).toBe('.txt'); + expect(path.extname('foo/bar')).toBe(''); + expect(path.extname('foo')).toBe(''); + }); + + it('should parse a path', () => + { + expect(path.parse('https://domain.com/')).toEqual(expect.objectContaining( + { root: 'https://domain.com/', dir: 'https://domain.com/', base: 'domain.com', ext: '.com', name: 'domain' } + )); + expect(path.parse('https://domain.com/path/to/file.txt')).toEqual(expect.objectContaining( + { root: 'https://domain.com/', dir: 'https://domain.com/path/to', base: 'file.txt', ext: '.txt', name: 'file' } + )); + expect(path.parse('file:///domain/path/to/file.txt')).toEqual(expect.objectContaining( + { root: 'file:///', dir: 'file:///domain/path/to', base: 'file.txt', ext: '.txt', name: 'file' } + )); + expect(path.parse('C:/domain.com/path/to/file.txt')).toEqual(expect.objectContaining( + { root: 'C:/', dir: 'C:/domain.com/path/to', base: 'file.txt', ext: '.txt', name: 'file' } + )); + expect(path.parse('C:/domain')).toEqual(expect.objectContaining( + { root: 'C:/', dir: 'C:/', base: 'domain', ext: '', name: 'domain' } + )); + expect(path.parse('/domain/path/to/file.txt')).toEqual(expect.objectContaining( + { root: '/', dir: '/domain/path/to', base: 'file.txt', ext: '.txt', name: 'file' } + )); + expect(path.parse('/domain')).toEqual(expect.objectContaining( + { root: '/', dir: '/', base: 'domain', ext: '', name: 'domain' } + )); + expect(path.parse('domain')).toEqual(expect.objectContaining( + { root: '', dir: '', base: 'domain', ext: '', name: 'domain' } + )); + expect(path.parse('/domain/path')).toEqual(expect.objectContaining( + { root: '/', dir: '/domain', base: 'path', ext: '', name: 'path' } + )); + }); + + it('should create absolute urls', () => + { + // relative paths + expect(path.toAbsolute('./img/browser.png', 'http://example.com/page-1/')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('./img/browser.png', 'http://example.com/page-1/')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('browser.png', 'http://example.com/page-1')).toEqual(`http://example.com/page-1/browser.png`); + expect(path.toAbsolute('img/browser.png', 'http://example.com/page-1/')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('windows.png', 'C:/foo/bar/')).toEqual(`C:/foo/bar/windows.png`); + expect(path.toAbsolute('windows.png', 'C:/foo/bar')).toEqual(`C:/foo/bar/windows.png`); + expect(path.toAbsolute('windows.png', 'C:\\foo\\bar\\')).toEqual(`C:/foo/bar/windows.png`); + expect(path.toAbsolute('mac.png', '/foo/bar/')).toEqual(`/foo/bar/mac.png`); + expect(path.toAbsolute('mac.png', '/foo/bar')).toEqual(`/foo/bar/mac.png`); + + // paths with extensions + expect(path.toAbsolute('./browser.png', 'http://example.com/page-1/index.html')) + .toEqual(`http://example.com/page-1/browser.png`); + expect(path.toAbsolute('./img/browser.png', 'http://example.com/page-1/index.html')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('img/browser.png', 'http://example.com/page-1/index.html')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('windows.png', 'C:/foo/bar/index.html')).toEqual(`C:/foo/bar/windows.png`); + expect(path.toAbsolute('mac.png', '/foo/bar/index.html')).toEqual(`/foo/bar/mac.png`); + + // path with query string + expect(path.toAbsolute('./browser.png', 'http://example.com/page-1/index.html?var=a#hash')) + .toEqual(`http://example.com/page-1/browser.png`); + expect(path.toAbsolute('./img/browser.png', 'http://example.com/page-1/index.html?var=a#hash')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('img/browser.png', 'http://example.com/page-1/index.html?var=a#hash')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('img/browser.png', 'http://example.com/page-1?var=a#hash')) + .toEqual(`http://example.com/page-1/img/browser.png`); + expect(path.toAbsolute('img/browser.png', 'http://example.com/page-1/?var=a#hash')) + .toEqual(`http://example.com/page-1/img/browser.png`); + + // root relative paths + expect(path.toAbsolute('/browser.png', undefined, 'http://example.com/')).toEqual(`http://example.com/browser.png`); + expect(path.toAbsolute('/browser.png', undefined, 'http://example.com')).toEqual(`http://example.com/browser.png`); + + expect(path.toAbsolute('/windows.png', undefined, 'C:/foo/')).toEqual(`C:/foo/windows.png`); + expect(path.toAbsolute('/windows.png', undefined, 'C:/foo')).toEqual(`C:/foo/windows.png`); + expect(path.toAbsolute('/windows.png', undefined, 'C:\\foo\\')).toEqual(`C:/foo/windows.png`); + expect(path.toAbsolute('/mac.png', undefined, '/foo/')).toEqual(`/foo/mac.png`); + expect(path.toAbsolute('/mac.png', undefined, '/foo')).toEqual(`/foo/mac.png`); + + // url is already absolute + expect(path.toAbsolute('http://example.com/browser.png')).toEqual(`http://example.com/browser.png`); + expect(path.toAbsolute('C:/windows.png')).toEqual(`C:/windows.png`); + expect(path.toAbsolute('C:\\windows.png')).toEqual(`C:/windows.png`); + }); + + it('should detect if path is a data url', () => + { + /* eslint-disable max-len */ + const valid = [ + 'data:image/png;base64,abc', + 'data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2', + 'data:image/svg+xml;charset=utf-8;name=bar.svg,%3Csvg%20xmlns%3D%22http%3A%2', + 'data:image/png;name=foo.png;base64,abc', + 'data:image/svg+xml;base64,abc', + 'data:,A%20brief%20note', + 'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E', + 'data:audio/mp3;base64,%3Ch1%3EHello!%3C%2Fh1%3E', + 'data:video/x-ms-wmv;base64,%3Ch1%3EHello!%3C%2Fh1%3E', + 'data:application/vnd.ms-excel;base64,PGh0bWw%2BPC9odG1sPg%3D%3D', + 'data:image/svg+xml;name=foobar%20(1).svg;charset=UTF-8,some-data', + 'data:image/svg+xml;name=lorem_ipsum.txt;charset=UTF-8,some-data', + 'data:text/html,' + ]; + + const invalid = [ + 'dataxbase64', + 'data:HelloWorld', + 'data:text/html;charset=,%3Ch1%3EHello!%3C%2Fh1%3E', + 'data:text/plain;name=@;base64,SGVsbG8sIFdvcmxkIQ%3D%3D', + 'data:text/html;charset,%3Ch1%3EHello!%3C%2Fh1%3E', + 'data:base64,abc', + '', + 'http://wikipedia.org', + 'base64', + 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dA' + ]; + /* eslint-enable max-len */ + + valid.forEach((value) => + { + expect(path.isDataUrl(value)).toBe(true); + }); + invalid.forEach((value) => + { + expect(path.isDataUrl(value)).toBe(false); + }); + }); +}); diff --git a/packages/utils/test/trimCanvas.tests.ts b/packages/utils/test/trimCanvas.tests.ts index 754192182c1..9b6171fab9d 100644 --- a/packages/utils/test/trimCanvas.tests.ts +++ b/packages/utils/test/trimCanvas.tests.ts @@ -1,9 +1,8 @@ import { trimCanvas } from '@pixi/utils'; -import { expect } from 'chai'; -describe('trimCanvas', function () +describe('trimCanvas', () => { - it('should trim the canvas', function () + it('should trim the canvas', () => { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); @@ -16,8 +15,8 @@ describe('trimCanvas', function () const trimmedImageData = trimCanvas(canvas); - expect(trimmedImageData.width).to.equal(9); - expect(trimmedImageData.height).to.equal(5); - expect(trimmedImageData.data).to.be.instanceOf(ImageData); + expect(trimmedImageData.width).toEqual(9); + expect(trimmedImageData.height).toEqual(5); + expect(trimmedImageData.data).toBeInstanceOf(ImageData); }); }); diff --git a/packages/utils/test/utils.tests.ts b/packages/utils/test/utils.tests.ts index b0140cb33fa..3e846b0cecf 100755 --- a/packages/utils/test/utils.tests.ts +++ b/packages/utils/test/utils.tests.ts @@ -1,40 +1,35 @@ import * as utils from '@pixi/utils'; -import { expect } from 'chai'; -describe('utils', function () +describe('utils', () => { - describe('uid', function () + describe('uid', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.uid) - .to.be.a('function'); + expect(utils.uid).toBeInstanceOf(Function); }); - it('should return a number', function () + it('should return a number', () => { - expect(utils.uid()) - .to.be.a('number'); + expect(utils.uid()).toBeNumber(); }); }); - describe('hex2rgb', function () + describe('hex2rgb', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.hex2rgb) - .to.be.a('function'); + expect(utils.hex2rgb).toBeInstanceOf(Function); }); // it('should properly convert number to rgb array'); }); - describe('hex2string', function () + describe('hex2string', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.hex2string) - .to.be.a('function'); + expect(utils.hex2string).toBeInstanceOf(Function); }); const testCases = [ @@ -56,220 +51,193 @@ describe('utils', function () { it(`should properly convert number 0x${num.toString(16)} to hex color string #${result}`, () => { - expect(utils.hex2string(num)).to.equals(result); + expect(utils.hex2string(num as number)).toEqual(result); }); }); }); - describe('rgb2hex', function () + describe('rgb2hex', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.rgb2hex) - .to.be.a('function'); + expect(utils.rgb2hex).toBeInstanceOf(Function); }); - it('should calculate correctly', function () + it('should calculate correctly', () => { - expect(utils.rgb2hex([0.3, 0.2, 0.1])).to.equals(0x4c3319); + expect(utils.rgb2hex([0.3, 0.2, 0.1])).toEqual(0x4c3319); }); // it('should properly convert rgb array to hex color string'); }); - describe('getResolutionOfUrl', function () + describe('getResolutionOfUrl', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.getResolutionOfUrl) - .to.be.a('function'); + expect(utils.getResolutionOfUrl).toBeInstanceOf(Function); }); // it('should return the correct resolution based on a URL'); }); - describe('decomposeDataUri', function () + describe('decomposeDataUri', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.decomposeDataUri) - .to.be.a('function'); + expect(utils.decomposeDataUri).toBeInstanceOf(Function); }); - it('should decompose a data URI', function () + it('should decompose a data URI', () => { const dataUri = utils.decomposeDataUri('data:image/png;base64,94Z9RWUN77ZW'); - expect(dataUri) - .to.be.an('object'); - expect(dataUri.mediaType) - .to.equal('image'); - expect(dataUri.subType) - .to.equal('png'); - expect(dataUri.charset) - .to.be.an('undefined'); - expect(dataUri.encoding) - .to.equal('base64'); - expect(dataUri.data) - .to.equal('94Z9RWUN77ZW'); + expect(dataUri).toBeObject(); + expect(dataUri.mediaType).toEqual('image'); + expect(dataUri.subType).toEqual('png'); + expect(dataUri.charset).toBeUndefined(); + expect(dataUri.encoding).toEqual('base64'); + expect(dataUri.data).toEqual('94Z9RWUN77ZW'); }); - it('should decompose a data URI with charset', function () + it('should decompose a data URI with charset', () => { const dataUri = utils.decomposeDataUri('data:image/svg+xml;charset=utf8;base64,PGRpdiB4bWxucz0Pg=='); - expect(dataUri) - .to.be.an('object'); - expect(dataUri.mediaType) - .to.equal('image'); - expect(dataUri.subType) - .to.equal('svg+xml'); - expect(dataUri.charset) - .to.equal('utf8'); - expect(dataUri.encoding) - .to.equal('base64'); - expect(dataUri.data) - .to.equal('PGRpdiB4bWxucz0Pg=='); + expect(dataUri).toBeObject(); + expect(dataUri.mediaType).toEqual('image'); + expect(dataUri.subType).toEqual('svg+xml'); + expect(dataUri.charset).toEqual('utf8'); + expect(dataUri.encoding).toEqual('base64'); + expect(dataUri.data).toEqual('PGRpdiB4bWxucz0Pg=='); }); - it('should decompose a data URI with charset without encoding', function () + it('should decompose a data URI with charset without encoding', () => { const dataUri = utils.decomposeDataUri('data:image/svg+xml;charset=utf8,PGRpdiB4bWxucz0Pg=='); - expect(dataUri) - .to.be.an('object'); - expect(dataUri.mediaType) - .to.equal('image'); - expect(dataUri.subType) - .to.equal('svg+xml'); - expect(dataUri.charset) - .to.equal('utf8'); - expect(dataUri.encoding) - .to.be.an('undefined'); - expect(dataUri.data) - .to.equal('PGRpdiB4bWxucz0Pg=='); + expect(dataUri).toBeObject(); + expect(dataUri.mediaType).toEqual('image'); + expect(dataUri.subType).toEqual('svg+xml'); + expect(dataUri.charset).toEqual('utf8'); + expect(dataUri.encoding).toBeUndefined(); + expect(dataUri.data).toEqual('PGRpdiB4bWxucz0Pg=='); }); - it('should return undefined for anything else', function () + it('should return undefined for anything else', () => { const dataUri = utils.decomposeDataUri('foo'); - expect(dataUri) - .to.be.an('undefined'); + expect(dataUri).toBeUndefined(); }); }); - describe('sayHello', function () + describe('sayHello', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.sayHello) - .to.be.a('function'); + expect(utils.sayHello).toBeInstanceOf(Function); }); }); - describe('isWebGLSupported', function () + describe('isWebGLSupported', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.isWebGLSupported) - .to.be.a('function'); + expect(utils.isWebGLSupported).toBeInstanceOf(Function); }); }); - describe('sign', function () + describe('sign', () => { - it('should return 0 for 0', function () + it('should return 0 for 0', () => { - expect(utils.sign(0)) - .to.be.equal(0); + expect(utils.sign(0)).toEqual(0); }); - it('should return -1 for negative numbers', function () + it('should return -1 for negative numbers', () => { for (let i = 0; i < 10; i += 1) { - expect(utils.sign(-Math.random())) - .to.be.equal(-1); + expect(utils.sign(-Math.random())).toEqual(-1); } }); - it('should return 1 for positive numbers', function () + it('should return 1 for positive numbers', () => { for (let i = 0; i < 10; i += 1) { - expect(utils.sign(Math.random() + 0.000001)) - .to.be.equal(1); + expect(utils.sign(Math.random() + 0.000001)).toEqual(1); } }); }); - describe('.removeItems', function () + describe('.removeItems', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.removeItems).to.be.a('function'); + expect(utils.removeItems).toBeInstanceOf(Function); }); - it('should return if the start index is greater than or equal to the length of the array', function () + it('should return if the start index is greater than or equal to the length of the array', () => { const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; utils.removeItems(arr, arr.length + 1, 5); - expect(arr.length).to.equal(10); + expect(arr.length).toEqual(10); }); - it('should return if the remove count is 0', function () + it('should return if the remove count is 0', () => { const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; utils.removeItems(arr, 2, 0); - expect(arr.length).to.equal(10); + expect(arr.length).toEqual(10); }); - it('should remove the number of elements specified from the array, starting from the start index', function () + it('should remove the number of elements specified from the array, starting from the start index', () => { const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; utils.removeItems(arr, 3, 4); - expect(arr).to.deep.equal([1, 2, 3, 8, 9, 10]); + expect(arr).toEqual([1, 2, 3, 8, 9, 10]); }); - it('should remove other elements if delete count is > than the number of elements after start index', function () + it('should remove other elements if delete count is > than the number of elements after start index', () => { const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; utils.removeItems(arr, 7, 10); - expect(arr).to.deep.equal([1, 2, 3, 4, 5, 6, 7]); + expect(arr).toEqual([1, 2, 3, 4, 5, 6, 7]); }); }); - describe('EventEmitter', function () + describe('EventEmitter', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.EventEmitter).to.be.a('function'); + expect(utils.EventEmitter).toBeInstanceOf(Function); }); }); - describe('isMobile', function () + describe('isMobile', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.isMobile).to.be.an('object'); + expect(utils.isMobile).toBeObject(); }); - it('should return a boolean for .any', function () + it('should return a boolean for .any', () => { - expect(utils.isMobile.any).to.be.a('boolean'); + expect(utils.isMobile.any).toBeBoolean(); }); }); - describe('earcut', function () + describe('earcut', () => { - it('should exist', function () + it('should exist', () => { - expect(utils.earcut).to.be.a('function'); + expect(utils.earcut).toBeInstanceOf(Function); }); }); }); diff --git a/rollup.config.js b/rollup.config.js index 7b18779cd77..be49c3a2f10 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,25 +1,25 @@ import path from 'path'; -import transpile from '@rollup/plugin-buble'; import resolve from '@rollup/plugin-node-resolve'; import { string } from 'rollup-plugin-string'; import sourcemaps from 'rollup-plugin-sourcemaps'; -import typescript from 'rollup-plugin-typescript'; +import esbuild from 'rollup-plugin-esbuild'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; -import { terser } from 'rollup-plugin-terser'; import jscc from 'rollup-plugin-jscc'; import alias from '@rollup/plugin-alias'; import workspacesRun from 'workspaces-run'; import repo from './lerna.json'; -import fs from 'fs'; const isProduction = process.env.NODE_ENV === 'production'; +const bundleTarget = 'es2017'; +const moduleTarget = 'es2020'; /** * Get the JSCC plugin for preprocessing code. * @param {boolean} debug Build is for debugging */ -function preprocessPlugin(debug) { +function preprocessPlugin(debug) +{ return jscc({ values: { _DEBUG: debug, @@ -33,7 +33,8 @@ function preprocessPlugin(debug) { * Convert a development file name to minified. * @param {string} name */ -function prodName(name) { +function prodName(name) +{ return name.replace(/\.(m)?js$/, '.min.$1js'); } @@ -47,39 +48,52 @@ async function main() }), commonjs(), json(), - typescript(), string({ include: [ '**/*.frag', '**/*.vert', ], }), - transpile(), ]; const plugins = [ preprocessPlugin(true), + esbuild({ + target: moduleTarget, + }), + ...commonPlugins + ]; + + const bundlePlugins = [ + preprocessPlugin(true), + esbuild({ + target: bundleTarget, + }), ...commonPlugins ]; const prodPlugins = [ preprocessPlugin(false), + esbuild({ + target: moduleTarget, + minify: true, + }), ...commonPlugins, - terser({ - output: { - comments: (node, comment) => comment.line === 1, - }, - }) ]; const prodBundlePlugins = [ alias({ entries: [{ find: /^(@pixi\/([^\/]+))$/, - replacement: '$1/dist/esm/$2.min.js', + replacement: '$1/dist/esm/$2.min.mjs', }] }), - ...prodPlugins + preprocessPlugin(false), + esbuild({ + target: bundleTarget, + minify: true, + }), + ...commonPlugins, ]; const compiled = (new Date()).toUTCString().replace(/GMT/g, 'UTC'); @@ -96,14 +110,6 @@ async function main() } }); - const namespaces = {}; - - // Create a map of globals to use for bundled packages - packages.forEach((pkg) => - { - namespaces[pkg.name] = pkg.config.namespace || 'PIXI'; - }); - packages.forEach((pkg) => { const { @@ -111,15 +117,14 @@ async function main() module, bundle, bundleModule, - bundleInput, - bundleOutput, - bundleNoExports, - standalone, version, dependencies, - peerDependencies } = pkg.config; + nodeDependencies, + peerDependencies, + pixiRequirements, + } = pkg.config; - let banner = [ + const banner = [ `/*!`, ` * ${pkg.name} - v${version}`, ` * Compiled ${compiled}`, @@ -131,9 +136,11 @@ async function main() // Check for bundle folder const external = Object.keys(dependencies || []) - .concat(Object.keys(peerDependencies || [])); + .concat(Object.keys(peerDependencies || [])) + .concat(nodeDependencies || []) + .concat(pixiRequirements || []); const basePath = path.relative(__dirname, pkg.dir); - let input = path.join(basePath, 'src/index.ts'); + const input = path.join(basePath, 'src/index.ts'); const freeze = false; results.push({ @@ -158,7 +165,8 @@ async function main() plugins, }); - if (isProduction) { + if (isProduction) + { results.push({ input, output: [ @@ -187,91 +195,56 @@ async function main() // this will package all dependencies if (bundle) { - let input = path.join(basePath, bundleInput || 'src/index.ts'); - - // TODO: remove check once all packages have been converted to typescript - if (!fs.existsSync(input)) - { - input = path.join(basePath, bundleInput || 'src/index.js'); - } - + const input = path.join(basePath, 'src/index.ts'); const file = path.join(basePath, bundle); const moduleFile = bundleModule ? path.join(basePath, bundleModule) : ''; - const external = standalone ? null : Object.keys(namespaces); - const globals = standalone ? null : namespaces; - const ns = namespaces[pkg.name]; - const name = pkg.name.replace(/[^a-z]+/g, '_'); let footer; - let nsBanner = banner; - - // Ignore self-contained packages like polyfills and unsafe-eval - // as well as the bundles pixi.js and pixi.js-legacy - if (!standalone) - { - if (bundleNoExports !== true) - { - footer = `Object.assign(this.${ns}, ${name});`; - } - - if (ns.includes('.')) - { - const base = ns.split('.')[0]; - - nsBanner += `\nthis.${base} = this.${base} || {};`; - } - - nsBanner += `\nthis.${ns} = this.${ns} || {};`; - } results.push({ input, - external, output: [ - Object.assign({ - banner: nsBanner, + { + name: 'PIXI', + banner, file, format: 'iife', freeze, - globals, - name, footer, sourcemap, - }, bundleOutput), - ...moduleFile ? [{ + }, + { banner, file: moduleFile, format: 'esm', freeze, sourcemap, - }] : [] + } ], treeshake: false, - plugins, + plugins: bundlePlugins, }); if (isProduction) { results.push({ input, - external, output: [ - Object.assign({ - banner: nsBanner, + { + name: 'PIXI', + banner, file: prodName(file), format: 'iife', freeze, - globals, - name, footer, sourcemap, - }, bundleOutput), - ...moduleFile ? [{ + }, + { banner, file: prodName(moduleFile), format: 'esm', freeze, sourcemap, - }] : [] + } ], treeshake: false, plugins: prodBundlePlugins, diff --git a/scripts/fixPeerVersions.ts b/scripts/fixPeerVersions.ts index d87e5a14e1c..896e9a81f6f 100644 --- a/scripts/fixPeerVersions.ts +++ b/scripts/fixPeerVersions.ts @@ -3,9 +3,7 @@ import path from 'path'; import fs from 'fs'; import util from 'util'; -/** - * Simplified interface for a package.json - */ +/** Simplified interface for a package.json */ interface Package { name: string; diff --git a/scripts/injectGlobalMixins.ts b/scripts/injectGlobalMixins.ts index 3315b27fdd6..15ec0e9058e 100644 --- a/scripts/injectGlobalMixins.ts +++ b/scripts/injectGlobalMixins.ts @@ -2,9 +2,7 @@ import workspacesRun from 'workspaces-run'; import path from 'path'; import fs from 'fs'; -/** - * simplified interface for a package.json - */ +/** simplified interface for a package.json */ interface SimplePackageJson { location: string @@ -14,6 +12,8 @@ interface SimplePackageJson /** * Adds global reference to the start of a packages `index.d.ts` file + * @param basePath + * @param dataToWrite */ function writeToIndex(basePath: string, dataToWrite: string): void { @@ -26,6 +26,7 @@ function writeToIndex(basePath: string, dataToWrite: string): void /** * Collect the list of packages in the project + * @param result */ async function getPackages(result: SimplePackageJson[] = []): Promise { @@ -49,30 +50,19 @@ async function getPackages(result: SimplePackageJson[] = []): Promise { - let pixiLocation: string; - let pixiLegacyLocation: string; - let pixiGlobalMixins = ''; - let pixiLegacyGlobalMixins = ''; - const packages = await getPackages(); - const legacyPackages = Object.keys(packages.find((pkg) => pkg.name === 'pixi.js-legacy').dependencies); - const pixiPackages = Object.keys(packages.find((pkg) => pkg.name === 'pixi.js').dependencies); + const bundles = packages.filter((p) => p.location.includes('bundles')).map((p) => p.name); + const locations = Array(bundles.length).fill(''); + const mixins = Array(bundles.length).fill(''); + const pkgs = bundles.map((bundle) => Object.keys(packages.find((pkg) => pkg.name === bundle).dependencies)); packages.forEach((pkg) => { const basePath = path.relative(process.cwd(), pkg.location); - if (pkg.name === 'pixi.js') - { - pixiLocation = pkg.location; - - return; - } - if (pkg.name === 'pixi.js-legacy') + if (bundles.includes(pkg.name)) { - pixiLegacyLocation = pkg.location; - - return; + locations[bundles.indexOf(pkg.name)] = pkg.location; } const globalDtsPath = path.resolve(basePath, './global.d.ts'); @@ -82,25 +72,24 @@ async function start(): Promise const pixiTypeData = `/// \n`; const packageTypeData = `/// \n`; - if (pixiPackages.includes(pkg.name)) - { - pixiGlobalMixins += pixiTypeData; - } - else if (legacyPackages.includes(pkg.name)) + pkgs.forEach((pixiPkgs, index) => { - pixiLegacyGlobalMixins += pixiTypeData; - } + if (pixiPkgs.includes(pkg.name)) + { + mixins[index] += pixiTypeData; + } + }); writeToIndex(basePath, packageTypeData); } }); - // write the total types to the main packages - let basePath = path.relative(process.cwd(), pixiLocation); + locations.forEach((location, index) => + { + const basePath = path.relative(process.cwd(), location); - writeToIndex(basePath, pixiGlobalMixins); - basePath = path.relative(process.cwd(), pixiLegacyLocation); - writeToIndex(basePath, pixiLegacyGlobalMixins); + writeToIndex(basePath, mixins[index]); + }); } start(); diff --git a/test/index.ts b/test/index.ts index 209a823c2fa..236ac55ab69 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,23 +1,17 @@ -import path from 'path'; -import { execFileSync } from 'child_process'; -import chai from 'chai'; -import sinonChai from 'sinon-chai'; +import { exec, execFileSync } from 'child_process'; import fs from 'fs'; -import type { FlossOptions } from 'floss'; +import path from 'path'; import type { PackageResult } from './packages'; -// Support for global otpions -declare global { - let options: FlossOptions; -} - // Support for the tsconfig path aliasing import 'tsconfig-paths/register'; +import parse from 'yargs-parser'; -// We only need to do this one time -chai.use(sinonChai); +const args = parse(process.argv, { + array: ['packages'] +}); -const requireAsStrings = (module, filename) => +const requireAsStrings = (module: any, filename: string) => { module.exports = fs.readFileSync(filename, 'utf8'); }; @@ -35,9 +29,7 @@ const packagesBuffer = execFileSync(cmd, [script]).toString(); const packages = JSON.parse(packagesBuffer) as PackageResult[]; // Filter any packages from the commandline options -const onlyPackages = options.args - .filter((arg) => arg.startsWith('--package=')) - .map((arg) => arg.replace('--package=', '')); +const onlyPackages = args.packages as string[] || []; // Filter the tests in case we have options to narrow scope const scopedPackages = !onlyPackages.length ? packages @@ -55,14 +47,8 @@ if (!availableSuites.length) console.log(`WARNING: Invalid package name${invalidNames.length > 1 ? 's' : ''}:`, `"${invalidNames.join('", "')}"`); } -for (const pkg of availableSuites) -{ - describe(pkg.name, () => - { - fs.readdirSync(pkg.tests) - .filter((file) => file.endsWith('.tests.ts')) - .map((file) => path.join(pkg.tests, file)) - // eslint-disable-next-line global-require - .forEach((file) => require(file)); - }); -} +const tests = availableSuites.map((pkg) => pkg.tests).join(' '); +const out = exec(`jest ${tests} --colors`); + +out.stdout.pipe(process.stdout); +out.stderr.pipe(process.stderr); diff --git a/test/jest-global-setup.ts b/test/jest-global-setup.ts new file mode 100644 index 00000000000..33488066fa1 --- /dev/null +++ b/test/jest-global-setup.ts @@ -0,0 +1,30 @@ +import { spawn } from 'child_process'; +import { join } from 'path'; + +// eslint-disable-next-line func-names +module.exports = async function () +{ + if (!process.env.GITHUB_ACTIONS) + { + const httpServerProcess = spawn('http-server', ['-c-1', `${join(process.cwd(), './packages')}`]); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.__SERVER__ = httpServerProcess; + + // give the server time to start + await new Promise((resolve) => + { + let data = ''; + + httpServerProcess.stdout.on('data', (chunk) => + { + data += chunk; + if (data.includes('Hit CTRL-C to stop the server')) + { + resolve(); + } + }); + }); + } +}; diff --git a/test/jest-global-teardown.ts b/test/jest-global-teardown.ts new file mode 100644 index 00000000000..2490f4691af --- /dev/null +++ b/test/jest-global-teardown.ts @@ -0,0 +1,20 @@ +import type { ChildProcess } from 'child_process'; + +// eslint-disable-next-line func-names +module.exports = async function () +{ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const httpServerProcess = (globalThis.__SERVER__ as ChildProcess | undefined); + + if (httpServerProcess) + { + const processClose = new Promise((resolve) => + { + httpServerProcess.on('close', resolve); + }); + + httpServerProcess.kill(); + await processClose; + } +}; diff --git a/test/packages.ts b/test/packages.ts index 94eda84403c..1c5cb8555f1 100644 --- a/test/packages.ts +++ b/test/packages.ts @@ -2,7 +2,8 @@ import path from 'path'; import fs from 'fs'; import workspacesRun from 'workspaces-run'; -interface PackageResult { +interface PackageResult +{ name: string; location: string; tests: string; diff --git a/tools/integration-tests/package.json b/tools/integration-tests/package.json index 33a108c761c..507e22e858a 100644 --- a/tools/integration-tests/package.json +++ b/tools/integration-tests/package.json @@ -1,23 +1,23 @@ { "name": "@internal/integration-tests", "private": true, - "version": "6.3.0", + "version": "7.0.0-alpha", "description": "Integration tests for PixiJS packages", "devDependencies": { - "@pixi/canvas-display": "6.3.0", - "@pixi/canvas-graphics": "6.3.0", - "@pixi/canvas-mesh": "6.3.0", - "@pixi/canvas-renderer": "6.3.0", - "@pixi/canvas-sprite": "6.3.0", - "@pixi/canvas-text": "6.3.0", - "@pixi/core": "6.3.0", - "@pixi/display": "6.3.0", - "@pixi/graphics": "6.3.0", - "@pixi/math": "6.3.0", - "@pixi/mesh": "6.3.0", - "@pixi/mesh-extras": "6.3.0", - "@pixi/sprite": "6.3.0", - "@pixi/text": "6.3.0", - "@pixi/utils": "6.3.0" + "@pixi/canvas-display": "7.0.0-alpha", + "@pixi/canvas-graphics": "7.0.0-alpha", + "@pixi/canvas-mesh": "7.0.0-alpha", + "@pixi/canvas-renderer": "7.0.0-alpha", + "@pixi/canvas-sprite": "7.0.0-alpha", + "@pixi/canvas-text": "7.0.0-alpha", + "@pixi/core": "7.0.0-alpha", + "@pixi/display": "7.0.0-alpha", + "@pixi/graphics": "7.0.0-alpha", + "@pixi/math": "7.0.0-alpha", + "@pixi/mesh": "7.0.0-alpha", + "@pixi/mesh-extras": "7.0.0-alpha", + "@pixi/sprite": "7.0.0-alpha", + "@pixi/text": "7.0.0-alpha", + "@pixi/utils": "7.0.0-alpha" } } diff --git a/tools/integration-tests/test/Bounds.tests.ts b/tools/integration-tests/test/Bounds.tests.ts index 0b4a84bac8f..603809a0ace 100644 --- a/tools/integration-tests/test/Bounds.tests.ts +++ b/tools/integration-tests/test/Bounds.tests.ts @@ -4,15 +4,13 @@ import { Sprite } from '@pixi/sprite'; import { Rectangle } from '@pixi/math'; import { Graphics } from '@pixi/graphics'; import { Text } from '@pixi/text'; -// import { SimplePlane } from '@pixi/mesh-extras'; -import { expect } from 'chai'; -describe('getBounds', function () +describe('getBounds', () => { - it('should register correct width/height with a LOADED Sprite', function () + it('should register correct width/height with a LOADED Sprite', () => { const parent = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); @@ -20,10 +18,10 @@ describe('getBounds', function () let bounds = sprite.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); sprite.position.x = 20; sprite.position.y = 20; @@ -33,30 +31,30 @@ describe('getBounds', function () bounds = sprite.getBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); bounds = sprite.getBounds(true); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); }); - it('should register correct width/height with Graphics', function () + it('should register correct width/height with Graphics', () => { const parent = new Container(); const graphics = new Graphics(); let bounds = graphics.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(0); - expect(bounds.height).to.equal(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(0); + expect(bounds.height).toEqual(0); graphics.beginFill(0xFF0000).drawCircle(0, 0, 10); @@ -64,10 +62,10 @@ describe('getBounds', function () bounds = graphics.getBounds(); - expect(bounds.x).to.equal(-10); - expect(bounds.y).to.equal(-10); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(-10); + expect(bounds.y).toEqual(-10); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); graphics.position.x = 20; graphics.position.y = 20; @@ -77,20 +75,20 @@ describe('getBounds', function () bounds = graphics.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(40); - expect(bounds.height).to.equal(40); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(40); + expect(bounds.height).toEqual(40); bounds = graphics.getBounds(true); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(40); - expect(bounds.height).to.equal(40); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(40); + expect(bounds.height).toEqual(40); }); - it('should register correct width/height with an empty Container', function () + it('should register correct width/height with an empty Container', () => { const parent = new Container(); @@ -100,10 +98,10 @@ describe('getBounds', function () let bounds = container.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(0); - expect(bounds.height).to.equal(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(0); + expect(bounds.height).toEqual(0); container.position.x = 20; container.position.y = 20; @@ -113,13 +111,13 @@ describe('getBounds', function () bounds = container.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(0); - expect(bounds.height).to.equal(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(0); + expect(bounds.height).toEqual(0); }); - it('should register correct width/height with a Container', function () + it('should register correct width/height with a Container', () => { const parent = new Container(); @@ -127,7 +125,7 @@ describe('getBounds', function () const graphics = new Graphics().beginFill(0xFF0000).drawCircle(0, 0, 10); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); container.addChild(sprite); @@ -142,29 +140,29 @@ describe('getBounds', function () let bounds = container.getBounds(); - expect(bounds.x).to.equal(30); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(80); - expect(bounds.height).to.equal(90); + expect(bounds.x).toEqual(30); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(80); + expect(bounds.height).toEqual(90); container.rotation = 0.1; bounds = container.getBounds(); - expect(bounds.x | 0).to.equal(26); - expect(bounds.y | 0).to.equal(22); - expect(bounds.width | 0).to.equal(73); - expect(bounds.height | 0).to.equal(97); + expect(bounds.x | 0).toEqual(26); + expect(bounds.y | 0).toEqual(22); + expect(bounds.width | 0).toEqual(73); + expect(bounds.height | 0).toEqual(97); bounds = container.getBounds(true); - expect(bounds.x | 0).to.equal(26); - expect(bounds.y | 0).to.equal(22); - expect(bounds.width | 0).to.equal(73); - expect(bounds.height | 0).to.equal(97); + expect(bounds.x | 0).toEqual(26); + expect(bounds.y | 0).toEqual(22); + expect(bounds.width | 0).toEqual(73); + expect(bounds.height | 0).toEqual(97); }); - it('should register correct width/height with an item that has already had its parent Container transformed', function () + it('should register correct width/height with an item that has already had its parent Container transformed', () => { const parent = new Container(); @@ -180,25 +178,25 @@ describe('getBounds', function () let bounds = container.getBounds(); - expect(bounds.x).to.equal(100); - expect(bounds.y).to.equal(100); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(100); + expect(bounds.y).toEqual(100); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); bounds = graphics.getBounds(true); - expect(bounds.x).to.equal(100); - expect(bounds.y).to.equal(100); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(100); + expect(bounds.y).toEqual(100); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); /* - it('should register correct width/height with a Mesh', function () + it('should register correct width/height with a Mesh', ()=> { const parent = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const plane = new SimplePlane(texture); @@ -209,24 +207,24 @@ describe('getBounds', function () let bounds = plane.getBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); plane.scale.x = 2; plane.scale.y = 2; bounds = plane.getBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); }); */ - it('should register correct width/height with an a DisplayObject is visible false', function () + it('should register correct width/height with an a DisplayObject is visible false', () => { const parent = new Container(); @@ -234,7 +232,7 @@ describe('getBounds', function () const graphics = new Graphics().beginFill(0xFF0000).drawCircle(0, 0, 10); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); container.addChild(sprite); @@ -251,35 +249,35 @@ describe('getBounds', function () let bounds = container.getBounds(); - expect(bounds.x).to.equal(30); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(30); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); sprite.renderable = false; bounds = container.getBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(0); - expect(bounds.height).to.equal(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toEqual(0); + expect(bounds.height).toEqual(0); bounds = sprite.getBounds(); - expect(bounds.x).to.equal(30); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(30); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct bounds of invisible Container', function () + it('should register correct bounds of invisible Container', () => { const parent = new Container(); const container = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); container.addChild(sprite); @@ -291,13 +289,13 @@ describe('getBounds', function () const bounds = container.getBounds(); - expect(bounds.x).to.equal(130); - expect(bounds.y).to.equal(120); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(130); + expect(bounds.y).toEqual(120); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct width/height with Container masked child', function () + it('should register correct width/height with Container masked child', () => { const parent = new Container(); @@ -305,7 +303,7 @@ describe('getBounds', function () const graphics = new Graphics().beginFill(0xFF0000).drawRect(0, 0, 10, 10); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); container.addChild(sprite); @@ -321,20 +319,20 @@ describe('getBounds', function () let bounds = graphics.getBounds(); - expect(bounds.x).to.equal(32); - expect(bounds.y).to.equal(23); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(bounds.x).toEqual(32); + expect(bounds.y).toEqual(23); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); bounds = container.getBounds(); - expect(bounds.x).to.equal(32); - expect(bounds.y).to.equal(23); - expect(bounds.width).to.equal(8); - expect(bounds.height).to.equal(7); + expect(bounds.x).toEqual(32); + expect(bounds.y).toEqual(23); + expect(bounds.width).toEqual(8); + expect(bounds.height).toEqual(7); }); - it('should register correct width/height with an a DisplayObject parent has moved', function () + it('should register correct width/height with an a DisplayObject parent has moved', () => { const parent = new Container(); @@ -353,13 +351,13 @@ describe('getBounds', function () const bounds = graphics.getBounds(); - expect(bounds.x).to.equal(-110); - expect(bounds.y).to.equal(-110); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(-110); + expect(bounds.y).toEqual(-110); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); }); - it('should register correct width/height with a Text Object', function () + it('should register correct width/height with a Text Object', () => { const parent = new Container(); @@ -374,23 +372,23 @@ describe('getBounds', function () let bounds = text.getBounds(); const bx = bounds.width; - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.be.greaterThan(0); - expect(bounds.height).to.greaterThan(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); + expect(bounds.width).toBeGreaterThan(0); + expect(bounds.height).toBeGreaterThan(0); text.text = 'hello!'; bounds = text.getBounds(); // this variable seems to be different on different devices. a font thing? - expect(bounds.width).to.not.equal(bx); + expect(bounds.width).not.toEqual(bx); }); - it('should return a different rectangle if getting local bounds after global bounds ', function () + it('should return a different rectangle if getting local bounds after global bounds ', () => { const parent = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); sprite.position.x = 20; @@ -403,23 +401,26 @@ describe('getBounds', function () const bounds = sprite.getBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); const localBounds = sprite.getLocalBounds(); - expect(localBounds.x).to.equal(0); - expect(localBounds.y).to.equal(0); - expect(localBounds.width).to.equal(10); - expect(localBounds.height).to.equal(10); + expect(Math.abs(localBounds.x)).toEqual(0); + expect(Math.abs(localBounds.y)).toEqual(0); + expect(localBounds.width).toEqual(10); + expect(localBounds.height).toEqual(10); }); - it('should ensure bounds respect the trim of a texture ', function () + it('should ensure bounds respect the trim of a texture ', () => { const parent = new Container(); - const baseTexture = new BaseRenderTexture(100, 100); + const baseTexture = new BaseRenderTexture({ + width: 100, + height: 100, + }); const orig = new Rectangle(0, 0, 100, 50); const frame = new Rectangle(2, 2, 50, 50); @@ -436,9 +437,9 @@ describe('getBounds', function () const bounds = sprite.getBounds(); - expect(bounds.x).to.equal(20); - expect(bounds.y).to.equal(20); - expect(bounds.width).to.equal(100); - expect(bounds.height).to.equal(50); + expect(bounds.x).toEqual(20); + expect(bounds.y).toEqual(20); + expect(bounds.width).toEqual(100); + expect(bounds.height).toEqual(50); }); }); diff --git a/tools/integration-tests/test/Container.tests.ts b/tools/integration-tests/test/Container.tests.ts index c50fea3e6eb..d07b4281368 100644 --- a/tools/integration-tests/test/Container.tests.ts +++ b/tools/integration-tests/test/Container.tests.ts @@ -2,15 +2,14 @@ import { Container } from '@pixi/display'; import { Graphics } from '@pixi/graphics'; import { Transform } from '@pixi/math'; import { MaskData } from '@pixi/core'; -import { expect } from 'chai'; import '@pixi/canvas-display'; -describe('Container', function () +describe('Container', () => { - describe('addChild', function () + describe('addChild', () => { - it('should recalculate added child correctly', function () + it('should recalculate added child correctly', () => { const parent = new Container(); const container = new Container(); @@ -18,7 +17,9 @@ describe('Container', function () parent.addChild(container); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); container.position.set(100, 200); container.updateTransform(); @@ -30,16 +31,16 @@ describe('Container', function () const bounds = graphics.getBounds(); - expect(bounds.x).to.be.equal(100); - expect(bounds.y).to.be.equal(200); - expect(bounds.width).to.be.equal(10); - expect(bounds.height).to.be.equal(10); + expect(bounds.x).toEqual(100); + expect(bounds.y).toEqual(200); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); }); - describe('removeChild', function () + describe('removeChild', () => { - it('should recalculate removed child correctly', function () + it('should recalculate removed child correctly', () => { const parent = new Container(); const container = new Container(); @@ -56,76 +57,85 @@ describe('Container', function () const bounds = graphics.getBounds(); - expect(bounds.x).to.be.equal(0); - expect(bounds.y).to.be.equal(0); + expect(bounds.x).toEqual(0); + expect(bounds.y).toEqual(0); }); }); - describe('width', function () + describe('width', () => { - it('should reflect scale', function () + it('should reflect scale', () => { const container = new Container(); const graphics = new Graphics(); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); container.addChild(graphics); container.scale.x = 2; - expect(container.width).to.be.equals(20); + expect(container.width).toEqual(20); }); - it('should adjust scale', function () + it('should adjust scale', () => { const container = new Container(); const graphics = new Graphics(); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); container.addChild(graphics); container.width = 20; - expect(container.width).to.be.equals(20); - expect(container.scale.x).to.be.equals(2); + expect(container.width).toEqual(20); + expect(container.scale.x).toEqual(2); }); }); - describe('height', function () + describe('height', () => { - it('should reflect scale', function () + it('should reflect scale', () => { const container = new Container(); const graphics = new Graphics(); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); container.addChild(graphics); container.scale.y = 2; - expect(container.height).to.be.equals(20); + expect(container.height).toEqual(20); }); - it('should adjust scale', function () + it('should adjust scale', () => { const container = new Container(); const graphics = new Graphics(); + graphics.beginFill(); graphics.drawRect(0, 0, 10, 10); + graphics.endFill(); container.addChild(graphics); container.height = 20; - expect(container.height).to.be.equals(20); - expect(container.scale.y).to.be.equals(2); + expect(container.height).toEqual(20); + expect(container.scale.y).toEqual(2); }); }); - describe('calculateBounds', function () + describe('calculateBounds', () => { - function createSquareContainer(x1, y1, x2, y2) + function createSquareContainer(x1: number, y1: number, x2: number, y2: number) { const container = new Container(); - container._calculateBounds = function () + // eslint-disable-next-line func-names + container['_calculateBounds'] = function () { this._bounds.addFrame(Transform.IDENTITY, x1, y1, x2, y2); }; @@ -133,7 +143,7 @@ describe('Container', function () return container; } - it('should take into account mask bounds after mask is set', function () + it('should take into account mask bounds after mask is set', () => { const maskedObject = createSquareContainer(1, 15, 11, 31); const parentContainer = new Container(); @@ -143,17 +153,17 @@ describe('Container', function () maskedObject.mask = new MaskData(createSquareContainer(5, 10, 35, 29)); bounds = parentContainer.getBounds(); - expect(bounds.x).to.equal(5); - expect(bounds.y).to.equal(15); - expect(bounds.width).to.equal(6); - expect(bounds.height).to.equal(14); + expect(bounds.x).toEqual(5); + expect(bounds.y).toEqual(15); + expect(bounds.width).toEqual(6); + expect(bounds.height).toEqual(14); maskedObject.mask = createSquareContainer(4, 9, 34, 32); bounds = parentContainer.getBounds(); - expect(bounds.x).to.equal(4); - expect(bounds.y).to.equal(15); - expect(bounds.width).to.equal(7); - expect(bounds.height).to.equal(16); + expect(bounds.x).toEqual(4); + expect(bounds.y).toEqual(15); + expect(bounds.width).toEqual(7); + expect(bounds.height).toEqual(16); }); }); }); diff --git a/tools/integration-tests/test/DisplayObject.tests.ts b/tools/integration-tests/test/DisplayObject.tests.ts index 415102b4515..5da6eca7de9 100644 --- a/tools/integration-tests/test/DisplayObject.tests.ts +++ b/tools/integration-tests/test/DisplayObject.tests.ts @@ -1,22 +1,23 @@ import { DisplayObject } from '@pixi/display'; import { MaskData } from '@pixi/core'; -import { expect } from 'chai'; import '@pixi/canvas-display'; -describe('DisplayObject', function () +describe('DisplayObject', () => { - describe('mask', function () + describe('mask', () => { - it('should change `renderable` field of maskedObject if we use MaskData', function () + it('should change `renderable` field of maskedObject if we use MaskData', () => { + // @ts-expect-error - Instantiating DisplayObject const maskedObject = new DisplayObject(); + // @ts-expect-error - Instantiating DisplayObject const maskObject = new DisplayObject(); maskedObject.mask = new MaskData(maskObject); - expect(maskObject.renderable).to.be.false; + expect(maskObject.renderable).toBe(false); maskedObject.mask = null; - expect(maskObject.renderable).to.be.true; + expect(maskObject.renderable).toBe(true); }); }); }); diff --git a/tools/integration-tests/test/getLocalBounds.tests.ts b/tools/integration-tests/test/getLocalBounds.tests.ts index be71f7ea7a1..ee940ab700e 100644 --- a/tools/integration-tests/test/getLocalBounds.tests.ts +++ b/tools/integration-tests/test/getLocalBounds.tests.ts @@ -2,32 +2,27 @@ import { Container } from '@pixi/display'; import { RenderTexture } from '@pixi/core'; import { CanvasRenderer } from '@pixi/canvas-renderer'; import { Sprite } from '@pixi/sprite'; -import { CanvasSpriteRenderer } from '@pixi/canvas-sprite'; import { Graphics } from '@pixi/graphics'; -import { CanvasGraphicsRenderer } from '@pixi/canvas-graphics'; import { Text } from '@pixi/text'; import { SimplePlane } from '@pixi/mesh-extras'; -import { CanvasMeshRenderer } from '@pixi/canvas-mesh'; -import { expect } from 'chai'; +import '@pixi/canvas-sprite'; +import '@pixi/canvas-graphics'; +import '@pixi/canvas-mesh'; import '@pixi/canvas-display'; import '@pixi/canvas-text'; -CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer); -CanvasRenderer.registerPlugin('graphics', CanvasGraphicsRenderer); -CanvasRenderer.registerPlugin('mesh', CanvasMeshRenderer); - -function withGL(fn) +function withGL(fn: () => void) { return !process.env.DISABLE_WEBGL ? fn : undefined; } -describe('getLocalBounds', function () +describe('getLocalBounds', () => { - it('should register correct local-bounds with a LOADED Sprite', function () + it('should register correct local-bounds with a LOADED Sprite', () => { const parent = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const sprite = new Sprite(texture); @@ -35,10 +30,10 @@ describe('getLocalBounds', function () let bounds = sprite.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); sprite.position.x = 20; sprite.position.y = 20; @@ -48,13 +43,13 @@ describe('getLocalBounds', function () bounds = sprite.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct local-bounds with Graphics', function () + it('should register correct local-bounds with Graphics', () => { const parent = new Container(); @@ -66,13 +61,13 @@ describe('getLocalBounds', function () const bounds = graphics.getLocalBounds(); - expect(bounds.x).to.equal(-10); - expect(bounds.y).to.equal(-10); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(bounds.x).toEqual(-10); + expect(bounds.y).toEqual(-10); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); }); - it('should register correct local-bounds with Graphics after clear', function () + it('should register correct local-bounds with Graphics after clear', () => { const parent = new Container(); @@ -84,10 +79,10 @@ describe('getLocalBounds', function () let bounds = graphics.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); graphics.clear(); graphics.beginFill(0xFF, 1); @@ -96,13 +91,13 @@ describe('getLocalBounds', function () bounds = graphics.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct local-bounds with Graphics after generateCanvasTexture and clear', function () + it('should register correct local-bounds with Graphics after generateCanvasTexture and clear', () => { const parent = new Container(); @@ -116,10 +111,10 @@ describe('getLocalBounds', function () graphics.generateCanvasTexture(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(20); - expect(bounds.height).to.equal(20); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(20); + expect(bounds.height).toEqual(20); graphics.clear(); graphics.beginFill(0xFF, 1); @@ -128,13 +123,13 @@ describe('getLocalBounds', function () bounds = graphics.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct local-bounds with an empty Container', function () + it('should register correct local-bounds with an empty Container', () => { const parent = new Container(); @@ -144,13 +139,13 @@ describe('getLocalBounds', function () const bounds = container.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(0); - expect(bounds.height).to.equal(0); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(Math.abs(bounds.width)).toEqual(0); + expect(Math.abs(bounds.height)).toEqual(0); }); - it('should register correct local-bounds with an item that has already had its parent Container transformed', function () + it('should register correct local-bounds with an item that has already had its parent Container transformed', () => { const parent = new Container(); @@ -166,17 +161,17 @@ describe('getLocalBounds', function () const bounds = container.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); }); - it('should register correct local-bounds with a Mesh', withGL(function () + it('should register correct local-bounds with a Mesh', withGL(() => { const parent = new Container(); - const texture = RenderTexture.create(10, 10); + const texture = RenderTexture.create({ width: 10, height: 10 }); const plane = new SimplePlane(texture); @@ -187,13 +182,13 @@ describe('getLocalBounds', function () const bounds = plane.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(10); - expect(bounds.height).to.equal(10); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(10); + expect(bounds.height).toEqual(10); })); - it('should register correct local-bounds with a cachAsBitmap item inside after a render', function () + it('should register correct local-bounds with a cachAsBitmap item inside after a render', () => { const parent = new Container(); @@ -206,25 +201,29 @@ describe('getLocalBounds', function () parent.addChild(graphic); - const renderer = new CanvasRenderer(100, 100); + const renderer = new CanvasRenderer({ + width: 100, + height: 100, + }); + // @ts-expect-error --- renderer.sayHello = () => { /* empty */ }; renderer.render(parent); const bounds = parent.getLocalBounds(); - expect(bounds.x).to.equal(0); - expect(bounds.y).to.equal(0); - expect(bounds.width).to.equal(100); - expect(bounds.height).to.equal(100); + expect(Math.abs(bounds.x)).toEqual(0); + expect(Math.abs(bounds.y)).toEqual(0); + expect(bounds.width).toEqual(100); + expect(bounds.height).toEqual(100); }); - it('should register correct local-bounds with a Text', function () + it('should register correct local-bounds with a Text', () => { const text = new Text('hello'); const bounds = text.getLocalBounds(); - expect(bounds.width).to.not.equal(0); - expect(bounds.height).to.not.equal(0); + expect(bounds.width).not.toEqual(0); + expect(bounds.height).not.toEqual(0); }); }); diff --git a/tsconfig.docs.json b/tsconfig.docs.json deleted file mode 100644 index aff5028d152..00000000000 --- a/tsconfig.docs.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6", - "outDir": "./dist/compiled", - "sourceMap": false, - "allowJs": true - }, - "include": [ - "bundles", - "packages", - "./global.d.ts" - ], - "exclude": [ - "node_modules", - "**/dist/**", - "**/lib/**", - "**/test/**", - "**/scripts/**", - "**/types/**", - "dist/**", - "bundles/*/*.d.ts", - "rollup.config.js", - ] -} diff --git a/tsconfig.json b/tsconfig.json index 971e031a25a..bf52fc3ba4e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es2020", "allowJs": false, "sourceMap": true, "removeComments": false, @@ -13,12 +13,11 @@ "allowSyntheticDefaultImports": true, "moduleResolution": "node", "resolveJsonModule": true, + "downlevelIteration": true, "baseUrl": "./", "paths": { "@pixi/*": [ - "packages/*/src", - "packages/filters/*/src", - "packages/canvas/*/src" + "packages/*/src" ], "pixi.js": [ "bundles/pixi.js/src" @@ -34,11 +33,8 @@ "node_modules", "**/dist/**", "**/lib/**", - "**/test/**", - "**/scripts/**", - "**/types/**", "bundles/**/*.d.ts", - "rollup.config.js" + "**/out/**" ], "ts-node": { "files": true, diff --git a/tsconfig.tests.json b/tsconfig.tests.json deleted file mode 100644 index 70f2865d459..00000000000 --- a/tsconfig.tests.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6", - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "module": "commonjs", - "baseUrl": "./", - "paths": { - "@pixi/*": [ - "packages/*/src", - "packages/filters/*/src", - "packages/canvas/*/src" - ] - }, - }, - "include": [ - "**/*.tests.ts", - "**/src/**.ts" - ] -} diff --git a/webdoc.conf.json b/webdoc.conf.json index bd8d999c9e9..161ed4aeb54 100644 --- a/webdoc.conf.json +++ b/webdoc.conf.json @@ -5,9 +5,7 @@ "source": { "include": [ "packages/*/src/**/*.ts", - "bundles/pixi.js/src/*.ts", - "packages/filters/*/src/**/*.(ts)", - "packages/canvas/*/src/**/*.(ts)"], + "bundles/pixi.js/src/*.ts"], "excludePattern": "(node_modules|lib|test)" }, "plugins": [